Postgres查询运行速度很慢

joh*_*nny 6 sql gis postgresql postgis postgresql-9.4

SELECT st.id
FROM
       station st, strike s
WHERE s.srikedatetime > (current_timestamp - interval '20 seconds')  and srikedatetime < current_timestamp
    AND ST_Distance_Sphere(st.Geometry, s.strikepoint)/1000 <= st.radius
Run Code Online (Sandbox Code Playgroud)

这个想法是当一次打击命中时,它可能是基于站点监视半径的多个站点的边界.我需要选择在过去20秒内受到任何罢工影响的所有电台.在20秒内我可以进行数千次攻击,并且每20秒执行一次查询时,CPU会变高,查询需要几分钟才能完成.当CPU不高时,它以毫秒运行.

查询计划:

"Nested Loop  (cost=0.42..505110.20 rows=21 width=7)"
"  Join Filter: ((_st_distance(geography(a.Geometry), geography(s.strikepoint), 0::double precision, false) / 1000::double precision) <= (a.radius)::double precision)"
"  ->  Index Only Scan using dup_strike_constraint on strike s  (cost=0.42..8.45 rows=1 width=36)"
"        Index Cond: ((srikedatetime > (now() - '00:00:20'::interval)) AND (srikedatetime < now()))"
"  ->  Seq Scan on station  st  (cost=0.00..505084.86 rows=62 width=549)"
Run Code Online (Sandbox Code Playgroud)

我尝试过内连接,就像这样

Inner JOIN strike s ON ST_Distance(a.Geometry, s.strikepoint) < 1
Run Code Online (Sandbox Code Playgroud)

并且还在where子句和分组中尝试了ST_DWithin仍然很慢.

ST_DWithin(s.strikepoint,a.Geometry, a.radius)
Run Code Online (Sandbox Code Playgroud)

请问有什么想法吗?我有罢工和车站表的索引.

st.strikepoint和a.geomerty列的数据类型是几何.坐标系是4326.谢谢!

Dan*_*Dan 1

您可以创建一个惰性物化视图来仅存储您需要的数据。如果您只查询一张表而不是连接“station”和“strike”表,速度会快很多。

显然,您的惰性表应该正确建立索引,特别是如果您不打算定期“清理”数据。

另一种选择是使用 TEMP 表来处理数据(如果不需要历史存储数据并且您在一个会话中处理数据)。TEMP 表仅对一个会话可见,并在会话结束时“消亡”。您可以随时创建它们并销毁它们,但在这种情况下您应该注意内存使用情况。

希望能帮助到你。