使ST_Distance查询在高负载下可扩展?

时间:2019-03-15 17:09:34

标签: postgresql postgis

我正在运行一个包含大型企业地址表的数据库服务器。已连接一个应用程序,该应用程序接收用户坐标和他们要查找的业务类型,并返回离该用户最近的业务。

最初,我的应用使用简单的SELECT语句查找最近的企业,返回了所有企业名称的表,并在应用的末尾进行了一些排序(这是用户和地址的坐标数据所在的位置)用于)找到与它们最接近的一个:

Select * from my_table where business_type = 'bakeries';

这对我来说并不理想,因为在应用程序末尾进行数据排序以找到最接近的数据时,它们会出现明显的延迟。我目前正在调查是否可以在数据库端更快地完成所有计算。因此,我发现了POSTGIS及其功能,以找到与输入最接近的坐标。利用其功能,我想出了针对每个用户请求执行的查询:

SELECT *, ST_Distance(ST_GeogFromText('SRID=4326;POINT(user_long user_lat)'), geom, false) as 
distance from my_table where business_type = 'Insurance'  order by distance limit 1;

这似乎是更快的响应,尤其是对于表中有很多列表的业务类型(例如保险公司)而言。但是,我注意到,当我尝试对传入的请求进行压力测试时,它的扩展规模惊人。对URL的500个并发请求会迅速导致数据库CPU使用率达到100%,因此这种方法在高峰时间将失败。

"Limit  (cost=12804.92 rows=1 width=261)"
"  ->  Sort  (cost=12804.91..12878.92 rows=29602 width=261)"
"        Sort Key: (_st_distance('0101000020E61000007AC7293A927F52C0D34D621058614440'::geography, (geom)::geography, '0'::double precision, false))"
"        ->  Index Scan using business_name_index on my_table  (cost=0.43..12656.90 rows=29602 width=261)"
"              Index Cond: (business_type = 'Insurance'::text)"

是否有一种方法可以使这种方法更可行,还是应该放弃这个想法并尝试其他方法?我知道一种替代方法是使用ST_DWithin查找特定半径内的所有最近地址(如here所示),但我无法定义最小距离,因为默认情况下某些距离可能太远。

2 个答案:

答案 0 :(得分:2)

我第二个叶夫根回答,假设您的业务坐标也是POINT而不是POLYGON之类的东西,这可能导致距离{{1 }}使用边界框。但是<->不使用索引,因此,如果性能是重中之重,那么这就是要走的路。

您可以在此处阅读有关特定问题的更多信息: http://postgis.net/workshops/postgis-intro/knn.html

您需要在ST_Distance()列上使用2d GiST索引,以使geom函数使用btw。

<->

您还可以考虑使用CREATE INDEX idx_mytable_geom ON my_table USING Gist(geom); 并将ST_GeomFromText()列转换为geom,因为geometries的表现似乎比geometries更好。

在此处找到更多信息: https://medium.com/coord/postgis-performance-showdown-geometry-vs-geography-ec99967da4f0

甚至更好地使用geographies,它也可以创建ST_MakePoint(),并且比geometries快。

在这里检查: https://gis.stackexchange.com/questions/58605/which-function-for-creating-a-point-in-postgis

尽管这将是一个较小的改进,因为您每次查询只能创建一个点,但它可能加起来。

所以您的代码如下:

ST_GeomFromtext()

这些是我的想法。

答案 1 :(得分:1)

我想,您仍然可以使用<->运算符(而不是ST_Distance())来提高应用程序的性能,因为它利用了空间索引并且可以更快地进行空间查找。