Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 使ST_距离查询在高负载下可扩展?_Postgresql_Postgis - Fatal编程技术网

Postgresql 使ST_距离查询在高负载下可扩展?

Postgresql 使ST_距离查询在高负载下可扩展?,postgresql,postgis,Postgresql,Postgis,我正在运行一个包含大量业务地址的数据库服务器。一个应用程序连接到它,它接收用户坐标和他们正在寻找的业务类型,并返回离该用户最近的业务 最初,我的应用程序使用一个简单的SELECT语句查找最近的企业,返回一个包含所有企业名称的表,并在应用程序端进行排序(这是使用用户坐标数据和地址的地方),以查找离他们最近的企业: Select * from my_table where business_type = 'bakeries'; 这对我来说似乎并不理想,因为应用程序端在对数据进行排序以找到最接近的数

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

最初,我的应用程序使用一个简单的SELECT语句查找最近的企业,返回一个包含所有企业名称的表,并在应用程序端进行排序(这是使用用户坐标数据和地址的地方),以查找离他们最近的企业:

Select * from my_table where business_type = 'bakeries';
这对我来说似乎并不理想,因为应用程序端在对数据进行排序以找到最接近的数据时出现了明显的半秒延迟。我目前正在调查是否可以在数据库端更快地完成所有计算。因此,我了解了它的功能,找到了与输入最接近的坐标。使用其功能,我提出了针对每个用户请求执行的查询:

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
查找某个半径内的所有最近地址(如图所示),但我无法定义最小距离,因为默认情况下,一些地址可能离用户太远。

我是第二个Yevgens答案,假设您的企业坐标也是
,而不是
多边形
或其他东西,这可能会导致彼此之间距离不一致,因为
使用边界框。但是
ST_Distance()
不使用索引,所以如果性能是最重要的,那么这就是方法

您可以在此处阅读有关具体问题的更多信息:

您需要在
geom
-列上有一个2d GiST索引,以便
函数使用btw

CREATE INDEX idx_mytable_geom ON my_table USING Gist(geom);

也可以考虑使用<代码> STGEOMFROM文本()/<代码>,并将您的<代码> GeOM列转换为<代码>几何> <代码> <代码>几何> <代码>似乎比<代码>地理< <代码>更好。p> 请在此处查找更多信息:

或者更好地使用
ST\u MakePoint()
,它还可以创建
几何图形
,并且比
ST\u GeomFromtext()更快

请点击此处:

虽然这只是一个小小的改进,因为每个查询只创建一个点,但它可能会累加起来

因此,您的代码如下所示:

SELECT a.*, ST_SetSRID(ST_MakePoint(lng lat), 4326) <-> a.geom as dist
FROM my_table a
where business_type = 'Insurance'
ORDER BY dist;
选择一个*,ST_设置网格(ST_生成点(lng lat),4326)a.geom作为距离
从我的桌子a
其中业务类型=‘保险’
按地区排序;

这些是我的想法。

我注意到一件事;因为您使用的是st_geogFromText,所以您的查询将Geom转换为地理位置。要么使用地理位置,要么使用geom,例如st_geomFromText(尽管我认为st_point更快)。