为什么使用postgre

本文详细介绍了PostgreSQL中JSON类型数据的操作方法,包括数据的插入、选择、更新和删除,以及如何使用JSON路径表达式进行数据检索。同时,深入探讨了PostGIS空间索引的原理与应用,对比了B-Tree、R-Tree和GiST索引的特点,提供了建立和优化GiST索引的指导。

1.支持json类型

准备数据

创建表:

create table ay_json_test(
    id varchar primary key,
    name varchar,
    json_value json
)

插入数据:

insert into ay_json_test values('001','ay','{  
  "ay_name":"阿毅",
  "home":{
      "type":{"interval":
          "5m"
      },
      "love":"now",
      "you":"None"
  },
  "values":{
      "event":["cpu_r","cpu_w"],
      "data":["cpu_r"],
      "threshold":[1,1]
  },
  "objects":{
      "al":"beauty"
  } 
}');

例一:选择数据

select id,name,json_value->>'ay_name' as ayName from ay_json_test where json_value ->>'ay_name' = '阿毅'

结果

 

这里写图片描述

例二:

select id,name,json_value->>'ay_name' as ayName,json_value ->> 'objects' as objects from ay_json_test 
where json_value ->>'ay_name' = '阿毅'

结果:

 

这里写图片描述

例三:数组元素选择

select json_value -> 'values'#>>'{data,0}' as objects from ay_json_test 
where json_value ->>'ay_name' = '阿毅'

这里写图片描述

例四:更新数据

update ay_json_test set json_value = '{  
  "ay_name":"阿毅_change",
  "home":{
      "type":{"interval_change":
          "5m"
      },
      "love":"now_change",
      "you":"None_change"
  },
  "values":{
      "event":["cpu_r_change","cpu_w_change"],
      "data":["cpu_r_change"],
      "array":[999,5]
  },
  "objects":{
      "al":"beauty"
  } 
}'
where json_value ->> 'ay_name' = '阿毅'

结果:

 

这里写图片描述

例五:删除数据

delete from ay_json_test where json_value ->> 'ay_name' = '阿毅_change'

结果,数据库已经没有数据了。

 



作者:阿_毅
链接:https://www.jianshu.com/p/0ed65e630fd0
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

2.PostGis空间索引支持好、几何类型和函数

索引的种类

PostgreSQL默认支持3种索引:B-Tree indexes, R-Tree indexes和 GiST indexes。

B-Tree用于可以在一个方向上排序的数据,如数字(numbers),字母(letters),日期(dates)。地理数据不能再一个方向上排序,所以B-Tree不能用于地理数据。

R-Trees是将数据分解成矩形,子矩形,子子矩形等。R-Trees被一些数据库用于地理数据的索引。但是PostgreSQL的R-Tree实现没有GiST实现那么健壮。

GiST(Generalized Search Trees)将数据分解成“东西在哪一边”,“东西覆盖什么”,“东西在什么里”,它可以用于广泛的数据结构,包括地理数据。PostGIS在GiST的基础上实现R-Tree去索引地理数据。

GiST的全称是“通用搜索树”,是索引的一般形式。

GiST用于加快各种不规则数据结构(整形数组,光谱数据等)的查询速度,这些数据不服从普通的B-Tree索引。

一旦地理数据表超过几千行,你就需要建立一个索引来加快数据的空间搜索(除非你的所有搜索都基于非地理属性)。

建立GiST索引的语法:

CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );

上面的语法是将建立2D索引。要建立PostGIS2.0+支持的n维索引,你可以用下面的语法:

CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield] gist_geometry_ops_nd);

建立空间索引是一个计算密集的工作:在一个1百万数据的表里,300MHZ的Solaris机器上,建立GiST索引大约需要1个小时。

建立索引之后,非常重要的是要强制PostgreSQL做优化查询的数据表分析:

VACUUM ANALYZE [table_name] [(column_name)];

-- 下面只在PostgreSQL 7.4以下(含)版本需要

SELECT UPDATE_GEOMETRY_STATS([table_name], [column_name]);

GiST索引比R-Tree索引有两个优势。

第一、GiST索引是"null值安全"的,索引的字段可以包括空值(null)。

第二、GiST索引支持"lossiness"的概念,这个概念对于大地理数据分厂重要(大于PostgreSQL的8K页面大小)。Lossiness允许PostgreSQL只存储地理信息中“重要”的一部分数据到索引中,仅计算边框。地理数据大于8K会导致R-Tree索引创建失败。

通常情况下,索引加快数据访问。一旦索引建立,查询规划器决定何时使用索引信息来加快查询,这个过程是透明的。

不幸的是,PostgreSQL查询规划器对GiST索引的优化不是很好,所以有些查询需要使用空间索引来替代默认的遍历全表。

如果你发现你的空间索引没有被使用,你可以做以下几件事情:

1、首先,确保分析收集了表的记录数量和分布,保证查询规划器使用更好的索引进行优化查询。从PostgreSQL8.0版本以后,运行VACUUM ANALYZE操作。你应该定期运行vaccuum。

2、如果vacuum不起作用,你可以强制规划器使用索引信息,通过使用SET ENABLE_SEQSCAN=OFF命令。你应该谨慎使用这个命令,并只在空间索引的查询中使用。一般来说,使用B-Tree索引时,查询规划器会更好的知道如何查询,一旦你运行了你的查询,应该考虑将ENABLE_SEQSCAN设置回来,这样其他查询可以正常利用规划器。

3、如果你发现查询规划器在全表遍历和索引使用上有错误,试着减少postgresql.conf中random_page_cost的值,或者使用SET random_page_cost=#命令。默认值是4,设置成1或2。递减该值使规划器更倾向于使用索引扫描。

检查索引的使用

尽管在PostgreSQL中的索引不需要维护或调整,但是检查索引在真实查询中的作用还是非常重要的。

检查独立查询中的索引使用情况可以使用EXPLAIN命令。

很难用跟一个标准化公式来决定需要创建哪些索引。

这里有一些典型事例:

1、总是先运行ANALYZE。这个命令收集统计数据在表中的分布值。这个值是估计查询结果条数所必须的,查询规划器根据它来实际分配查询消耗。在缺乏任何真正的统计数据时,会使用一些假设的默认值,这是几乎可以肯定是不准确的。在不运行ANALYZE时就检查索引的使用是错误的。

2、使用真实数据进行实验。

3、当索引未被使用时,可以强制使用。有些运行参数可以关掉各种规划类型。

例如关闭顺序扫描(ENABLE_SEQUSCAN)和嵌套循环连接(ENABLE_NESTLOOP),关掉这些最基本的规划,可以破事系统使用不同的规划。如果系统仍然使用循序扫描或前台循环连接则可能是不适用索引的根本原因。比如查询条件不匹配索引。

4、如果强制使用索引时,索引被使用了,那么有两种可能:使用的索引不恰当或者查询规划器的消耗估计不反应真实情况。

可以用EXPLAIN ANALYZE命令找原因。

5、如果证明是查询规划器的消耗估计错误,有两种可能:

1)总消耗是从每行节点的时间倍数计算得来。估计该规划节点的消耗可以通过运行参数进行调整。

2)不准确的评估是由于统计数据不足造成的。有可能可以通过调整statistics-gathering参数来改善。



作者:安易学车
链接:https://www.jianshu.com/p/b5673bf18141
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

postgresql支持的几何类型如下表:

名字存储空间描述表现形式
point16字节平面上的点(x,y)
line32字节直线{A,B,C}
lseg32字节线段((x1,y1),(x2,y2))
box32字节矩形((x1,y1),(x2,y2))
path16+16n字节闭合路径((x1,y1),...)
path16+16n字节开放路径[(x1,y1),...]
polygon40+16n字节多边形((x1,y1),...)
circle24字节<(x,y),r> 

示例:

复制代码

test=# select point'(1,1)';
 point 
-------
 (1,1)
(1 row)

test=# select line'{1,1,1}';
  line   
---------
 {1,1,1}
(1 row)

test=# select lseg'(1,1),(2,2)';
     lseg      
---------------
 [(1,1),(2,2)]
(1 row)

test=# select box'(1,1),(2,2)';
     box     
-------------
 (2,2),(1,1)
(1 row)

test=# select path'(1,1),(2,2),(2,1)';
        path         
---------------------
 ((1,1),(2,2),(2,1))
(1 row)

test=# select path'[(1,1),(2,2),(2,1)]';
        path         
---------------------
 [(1,1),(2,2),(2,1)]
(1 row)

test=# select polygon'((1,1),(2,2),(2,1))';
       polygon       
---------------------
 ((1,1),(2,2),(2,1))
(1 row)

test=# select circle'<(0,0),1>';
  circle   
-----------
 <(0,0),1>
(1 row)

复制代码

 

操作符

操作符描述示例结果
+平移select box '((0,0),(1,1))' + point '(2.0,0)';(3,1),(2,0)
-平移select box '((0,0),(1,1))' - point '(2.0,0)';(-1,1),(-2,0)
*伸缩/旋转select box '((0,0),(1,1))' * point '(2.0,0)';(2,2),(0,0)
/伸缩/旋转select box '((0,0),(2,2))' / point '(2.0,0)';(1,1),(0,0)
#交点或者交面select box'((1,-1),(-1,1))' # box'((1,1),(-1,-1))';(1,1),(-1,-1)
#path或polygon的顶点数select #path'((1,1),(2,2),(2,1))';3
@-@长度或周长select @-@ path'((1,1),(2,2),(2,1))';3.41421356237309
@@中心select @@ circle'<(0,0),1>';(0,0)
##第一个操作数和第二个操作数的最近点select point '(0,0)' ## lseg '((2,0),(0,2))';(1,1)
<->间距select circle '<(0,0),1>' <-> circle '<(5,0),1>';3
&&是否有重叠select box '((0,0),(1,1))' && box '((0,0),(2,2))';t
<<是否严格在左select circle '((0,0),1)' << circle '((5,0),1)';t
>>是否严格在右select circle '((0,0),1)' >> circle '((5,0),1)';f
&<是否没有延伸到右边select box '((0,0),(1,1))' &< box '((0,0),(2,2))';t
&>是否没有延伸到左边select box '((0,0),(3,3))' &> box '((0,0),(2,2))';t
<<|是否严格在下select box '((0,0),(3,3))' <<| box '((3,4),(5,5))';t
|>>是否严格在上select box '((3,4),(5,5))' |>> box '((0,0),(3,3))';t
&<|是否没有延伸到上面select box '((0,0),(1,1))' &<| box '((0,0),(2,2))';t
|&>是否没有延伸到下面select box '((0,0),(3,3))' |&> box '((0,0),(2,2))';t
<^是否低于(允许接触)select box '((0,0),(3,3))' <^ box '((3,3),(4,4))';t
>^是否高于(允许接触)select box '((0,0),(3,3))' >^ box '((3,3),(4,4))';f
?#是否相交select lseg '((-1,0),(1,0))' ?# box '((-2,-2),(2,2))';t
?-是否水平对齐select ?- lseg '((-1,1),(1,1))';t
?-两边图形是否水平对齐select point '(1,0)' ?- point '(0,0)';t
?|是否竖直对齐select ?| lseg '((-1,0),(1,0))';f
?|两边图形是否竖直对齐select point '(0,1)' ?| point '(0,0)';t
?-|是否垂直select lseg '((0,0),(0,1))' ?-| lseg '((0,0),(1,0))';t
?||是否平行select lseg '((-1,0),(1,0))' ?|| lseg '((-1,2),(1,2))';t
@>是否包含select circle '((0,0),2)' @> point '(1,1)';t
<@是否包含于或在图形上select point '(1,1)' <@ circle '((0,0),2)';t
~=是否相同select polygon '((0,0),(1,1))' ~= polygon '((1,1),(0,0))';t

 

函数

函数返回值类型描述示例结果
area(object)double precision面积select area(circle'((0,0),1)');3.14159265358979
center(object)point中心select center(box'(0,0),(1,1)');(0.5,0.5)
diameter(circle)double precision圆周长select diameter(circle '((0,0),2.0)');4
height(box)double precision矩形竖直高度select height(box '((0,0),(1,1))');1
isclosed(path)boolean是否为闭合路径select isclosed(path '((0,0),(1,1),(2,0))');t
isopen(path)boolean是否为开放路径select isopen(path '[(0,0),(1,1),(2,0)]');t
length(object)double precision长度select length(path '((-1,0),(1,0))');4
npoints(path)intpath中的顶点数select npoints(path '[(0,0),(1,1),(2,0)]');3
npoints(polygon)int多边形的顶点数select npoints(polygon '((1,1),(0,0))');2
pclose(path)path将开放path转换为闭合pathselect pclose(path '[(0,0),(1,1),(2,0)]'); ((0,0),(1,1),(2,0))
popen(path)path将闭合path转换为开放pathselect popen(path '((0,0),(1,1),(2,0))');[(0,0),(1,1),(2,0)]
radius(circle)double precision圆半径select radius(circle '((0,0),2.0)');2
width(box)double precision矩形的水平长度select width(box '((0,0),(1,1))');1

类型转换函数

函数返回类型描述示例结果
box(circle)box圆形转矩形select box(circle '((0,0),2.0)');(1.41421356237309,1.41421356237309),(-1.41421356237309,-1.41421356237309)
box(point)box点转空矩形select box(point '(0,0)');(0,0),(0,0)
box(point, point)box点转矩形select box(point '(0,0)', point '(1,1)');(1,1),(0,0)
box(polygon)box多边形转矩形select box(polygon '((0,0),(1,1),(2,0))');(2,1),(0,0)
bound_box(box, box)box将两个矩形转换成一个边界矩形select bound_box(box '((0,0),(1,1))', box '((3,3),(4,4))');(4,4),(0,0)
circle(box)circle矩形转圆形select circle(box '((0,0),(1,1))');<(0.5,0.5),0.707106781186548>
circle(point, double precision)circle圆心与半径转圆形select circle(point '(0,0)', 2.0);<(0,0),2>
circle(polygon)circle多边形转圆形select circle(polygon '((0,0),(1,1),(2,0))');<(1,0.333333333333333),0.924950591148529>
line(point, point)line点转直线select line(point '(-1,0)', point '(1,0)');{0,-1,0}
lseg(box)lseg矩形转线段select lseg(box '((-1,0),(1,0))');[(1,0),(-1,0)]
lseg(point, point)lseg点转线段select lseg(point '(-1,0)', point '(1,0)');[(-1,0),(1,0)]
path(polygon)path多边形转pathselect path(polygon '((0,0),(1,1),(2,0))');((0,0),(1,1),(2,0))
point(double precision, double precision)pointselect point(23.4, -44.5);(23.4,-44.5)
point(box)point矩形转点select point(box '((-1,0),(1,0))');(0,0)
point(circle)point圆心select point(circle '((0,0),2.0)');(0,0)
point(lseg)point线段中心select point(lseg '((-1,0),(1,0))');(0,0)
point(polygon)point多边形的中心select point(polygon '((0,0),(1,1),(2,0))');(1,0.333333333333333)
polygon(box)polygon矩形转4点多边形select polygon(box '((0,0),(1,1))');((0,0),(0,1),(1,1),(1,0))
polygon(circle)polygon圆形转12点多边形select polygon(circle '((0,0),2.0)');

((-2,0),(-1.73205080756888,1),(-1,1.73205080756888),(-1.22460635382238e-16,2),(1,1.73205080756888),(1.73205080756888,1),(2,2.4492127
0764475e-16),(1.73205080756888,-0.999999999999999),(1,-1.73205080756888),(3.67381906146713e-16,-2),(-0.999999999999999,-1.73205080756
888),(-1.73205080756888,-1))

polygon(npts, circle)polygon圆形转npts点多边形select polygon(12, circle '((0,0),2.0)');

((-2,0),(-1.73205080756888,1),(-1,1.73205080756888),(-1.22460635382238e-16,2),(1,1.73205080756888),(1.73205080756888,1),(2,2.4492127
0764475e-16),(1.73205080756888,-0.999999999999999),(1,-1.73205080756888),(3.67381906146713e-16,-2),(-0.999999999999999,-1.73205080756
888),(-1.73205080756888,-1))

polygon(path)polygon将path转多边形select polygon(path '((0,0),(1,1),(2,0))');((0,0),(1,1),(2,0))

 

原文链接:

https://www.postgresql.org/docs/9.6/static/functions-geometry.html

 

如果有兴趣学习地图相关的,大家可以去看一下postgis。

https://github.com/digoal/blog/blob/master/201601/20160119_01.md?spm=a2c4e.11153940.blogcont111793.33.50575bf0QF1whc&file=20160119_01.md

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值