我目前有一個大表mivehdetailedtrajectory
(25B行)和一個小表cell_data_tower
(400行),我需要使用PostGIS加入。具體來說,我需要運行這個查詢:優化大型PostGIS查詢
SELECT COUNT(traj.*), tower.id
FROM cell_data_tower tower LEFT OUTER JOIN mivehdetailedtrajectory traj
ON ST_Contains(tower.geom, traj.location)
GROUP BY tower.id
ORDER BY tower.id;
它錯誤出來生氣,它不能寫入磁盤。這似乎是不可思議的選擇,所以我跑了說明: 注意:gserialized_gist_joinsel:jointype 1不支持
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------
Sort (cost=28905094882.25..28905094883.25 rows=400 width=120)
Sort Key: tower.id
-> HashAggregate (cost=28905094860.96..28905094864.96 rows=400 width=120)
-> Nested Loop Left Join (cost=0.00..28904927894.80 rows=33393232 width=120)
Join Filter: ((tower.geom && traj.location) AND _st_contains(tower.geom, traj.location))
-> Seq Scan on cell_data_tower tower (cost=0.00..52.00 rows=400 width=153)
-> Materialize (cost=0.00..15839886.96 rows=250449264 width=164)
-> Seq Scan on mivehdetailedtrajectory traj (cost=0.00..8717735.64 rows=250449264 width=164)
我不明白爲什麼Postgres的認爲它應該兌現內部表。另外,我不明白一般的計劃是誠實的。似乎應該將cell_data_tower表保存在內存中,並遍歷mivehdetailedtrajectory表。關於如何優化這個(a)運行,(b)在合理的時間內這樣做的任何想法。具體來說,這似乎應該在不到1天的時間內完成。
編輯:需要大量內存的Postgres 9.3版
請添加PostgreSQL的版本。 –
可能是一個愚蠢的問題,但你確實有一個mivehdetailedtrajectory空間索引?在這種查詢中,你並不需要編寫左外連接,因爲本質上你正在進行完全連接,但是通過「空間」連接來限制結果。如果用逗號替換左外連接,則可能會得到不同的計劃。 –
我有類似的問題與磁盤空間用散列連接。您可以嘗試設置enable_hashagg = off和/或enable_hashjoin = off。這可能會使查詢計劃變得更糟(它的確如此),但它會切換到使用嵌套循環連接,儘管速度較慢,但不會嚼碎磁盤空間。最終,如果你沒有空間索引,那麼你無論如何都要做一個雙循環,每次只檢查ST_Contains。正如Jakub指出的那樣,我冒昧地爲您的選擇添加了tower.id。 –