postgresql 基于GeoHash的邻近服务的可扩展性

jrcvhitl  于 12个月前  发布在  PostgreSQL
关注(0)|答案(1)|浏览(123)

我在阅读Alex Xu的System Design Volume 2中的Proximity Service一章,其中一种用于定位特定位置附近的企业的方法涉及使用GeoHash。然而,当使用这种方法来查找附近的企业时,LIKE查询是必要的,例如WHERE geohash LIKE '9qbwac %'。尽管Postgres中的geohash列上有索引,此查询将触发全表扫描。2随着业务数量的增长,全表扫描可能会显著减慢该过程。3因此,这种方法真的更好吗?
我尝试在postgres中构建一个伪表,索引在geoHash列上,并插入100万个随机条目。运行一个带有LIKE操作符的WHERE子句会进行全表扫描。

5uzkadbs

5uzkadbs1#

我的猜测是你没有建立正确的索引,能够支持基于like^@的查询,正如@jjanes已经建议的那样。这里有一个例子demo at db<>fiddle,比较基于geohash和常规PostGIS几何的操作。对于前缀检查,text_pattern_ops就足够了,但是我使用pg_trgm也是为了比较<->distance/相似性度量(忽略了一个事实,那不是基于geohash计算距离的真正方法)。
PostGIS:

prepare postgis_based2 as
select id,business_name,x,y,geohash
from business
where st_dwithin((select geom from business where id=42),geom,1)
limit 5;

explain analyze execute postgis_based2;
execute postgis_based2;

字符串
| 查询计划|
| --|
| 限制(成本=8.71..93.30行=5宽度=62)(实际时间=0.114..0.120行=5循环=1)|
|   InitPlan 1(返回$0)|
|     ->使用business_pkey对业务business_1进行索引扫描(cost=0.29..8.31 rows=1 width=32)(实际时间=0.007..0.007 rows=1 loops=1)|
|           (id = 42)|
|   ->在业务上使用geom_idx进行索引扫描(成本=0.41..169.58行=10宽度=62)(实际时间=0.112..0.118行=5循环=1)|
|         索引条件:(geom && st_expand($0,'1'::double precision))|
|         过滤器:st_dwithin($0,geom,'1'::double precision)|
|         过滤器删除的错误:1|
| 计划时间:0.367 ms|
| 执行时间:0.187 ms|
| ID|企业名称|X| y| geohash|
| --|--|--|--|--|
| 22307 |企业_22307| 165.213429396186| -45.3420063495878 |pxvqp98xxvmudmj97vkf|
| 83713 |业务_83713| 164.855609921369| -45.0914942385985 |pxvprrk5n0hr95qn5u8w|
| 93720 |业务_93720| 164.990241156698| -45.0564514554435 |pxvrdmwppk8tgw7n39vb|
| 42 |商业_42| 164.28489159467| -45.2105222171467 |pxuyf3ste7vf53zk17fj|
| 6309 |业务_6309| 164.818000468193| -45.2836125675001 |pxvnqs2gcfb9hsmg5tru|
Geohash:

prepare geohash_based2 as
select id,business_name,x,y,geohash
from business
where geohash like (select left(geohash,2)||'%' from business where id=42)
limit 5;

explain analyze execute geohash_based2;
execute geohash_based2;


| 查询计划|
| --|
| 限制(成本=8.60..26.28行=5宽度=62)(实际时间=0.124..0.229行=5循环=1)|
|   InitPlan 1(返回$0)|
|     ->使用business_pkey对业务business_1进行索引扫描(cost=0.29..8.32 rows=1 width=32)(实际时间=0.008..0.008 rows=1 loops=1)|
|           (id = 42)|
|   ->使用business_geohash_idx对业务进行索引扫描(cost=0.28..1769.03 rows=500 width=62)(实际时间=0.123..0.227 rows=5 loops=1)|
|         索引条件:(geohash ~~ $0)|
| 规划时间:0.117 ms|
| 执行时间:0.246 ms|
| ID|企业名称|X| y| geohash|
| --|--|--|--|--|
| 6455 |企业_6455| 161.767801616675| -45.6640432705416 |pxgh1p5ewvre95j5rkyx|
| 987 |商业_987| 157.535974430581| -46.4991816873455 |px8p2z44wk22zke1jqpm|
| 21938 |企业_21938| 157.564399796883| -45.6057628837771 |pxbh93wzhtegxh8m2kv9|
| 97368 |业务_97368| 162.477336834207| -50.1455647066609 |px5d9r22um5qfvt4msbs|
| 42804 |业务_42804| 167.725818809955| -47.204996981719 |pxx72ww4yyg0svjhde6e|

相关问题