空间索引是postgis中十分重要的功能,一个数据库中如果不支持索引那几乎是没法使用的。postgis中空间索引通过将数据组织到搜索树中来加快搜索速度,搜索树可以快速遍历以查找特定记录。
对于空间的几何图形,不是通过btree索引来加速查询,而是通过gist索引。gist索引是通过r_tree的结构来实现对空间类型数据的索引查询,其结构类似于btree索引。
r树介绍:https://zh.wikipedia.org/wiki/R%E6%A0%91
gist索引是怎么工作的呢?
比如上面这个图片,查询和黄星相交的对象,即是图中的红线,gist索引不能索引几何要素本身,而是索引几何要素的边界框(bouding box)。
所以在索引计算时,其实是先判断那些边界框和黄星所在的框相交,显然是红线和蓝线的框,然后再进行哪些直线与黄星相交的精确计算。
使用语法:
postgis=# create index idx_t_pos_1 on t_pos using gist(pos);
CREATE INDEX
对一张数据量1000的表进行全表扫描:
postgis=# select count(*) from t_pos;
count
-------
1000
(1 row)
postgis=# explain (analyze,buffers,timing) select * from t_pos where pos && st_astext(' POINT(73.689759 3.880185)');
QUERY PLAN
-------------------------------------------------------------------------------------------------
Seq Scan on t_pos (cost=0.00..21.50 rows=1 width=36) (actual time=0.012..0.600 rows=1 loops=1)
Filter: (pos && '0101000000C9C7EE02256C52402670EB6E9E0A0F40'::geometry)
Rows Removed by Filter: 999
Buffers: shared hit=9
Planning Time: 0.231 ms
Execution Time: 0.612 ms
(6 rows)
加上索引,使用索引查询:
postgis=# explain (analyze,buffers,timing) select * from t_pos where pos && st_astext(' POINT(73.689759 3.880185)');
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Index Scan using idx_t_pos_1 on t_pos (cost=0.14..8.16 rows=1 width=36) (actual time=0.057..0.058 rows=1 loops=1)
Index Cond: (pos && '0101000000C9C7EE02256C52402670EB6E9E0A0F40'::geometry)
Buffers: shared hit=3
Planning Time: 0.228 ms
Execution Time: 0.074 ms
(5 rows)
可以看到性能有了明显的提升!