2013-04-11 54 views
1

我有一個使用案例,其中兩組數據與昂貴的空間謂詞連接。爲了並行化查詢,我將空間Universe劃分爲瓦片(數千個數量級),以便只有屬於同一瓦片的記錄需要使用空間謂詞進行測試。查詢如下:大數據集上的空間連接查詢優化

SELECT ST_Area(ST_Intersection(A.polygon, B.polygon)) 
    /ST_Area(ST_Union(A.polygon, B.polygon)) AS a_ratio 
FROM spatial_table_a A 
JOIN spatial_table_b B ON ST_Intersects(A.polygon, B.polygon) 
WHERE A.tilename = B.tilename; 

理想地,查詢計劃應根據tilename散列記錄,那麼執行空間謂詞使用任一索引掃描檢查ST_Intersects加入或嵌套循環連接。

但是,我現在得到的是一個過早執行空間連接的次優計劃。該計劃如下所示:

-> Hash Join (cost=759468.44..377874772.26 rows=2610 width=18) 
     Hash Cond: "outer"."?column4?" = "inner"."?column4?" 
      Join Filter: a.polygon && b.polygon AND _st_intersects(a.polygon, b.polygon) 
      -> Seq Scan on spatial_table_b b (cost=0.00..409556.95 rows=288816 width=1034) 
      -> Hash (cost=375827.86..375827.86 rows=283522 width=946) 
        -> Seq Scan on spatial_table_a a (cost=0.00..375827.86 rows=283522 width=946) 

所以,我的問題是:如何可以強制查詢優化器產生一個更好的計劃(這基本上改變了連接順序)?

+0

對不起,我編輯了空格。我不喜歡水平滾動。 – wildplasser

+0

如果它明顯是連接邏輯的一部分,爲什麼不在連接子句中包含'A.tilename = B.tilename'? –

+0

@JakubKania所以你的意思是加入spatial_table_b B ON ST_Intersects(A.polygon,B.polygon)AND A.tilename = B.tilename?查詢計劃沒有變化。 – ablimit

回答

1

如何:

SELECT ST_Area(ST_Intersection(a, b)) 
    /ST_Area(ST_Union(a, b)) AS a_ratio 
FROM 
(
SELECT a.polygon AS a, b.polygon AS b 
FROM spatial_table_a A 
JOIN spatial_table_b B 
    ON A.tilename = B.tilename 
OFFSET 0 
) AS q 
WHERE ST_Intersects(a, b); 

這應該強制查詢規劃先加入上tilename兩個表,然後才檢查兩個多邊形相交。這會給你一個不同的查詢計劃,但我不確定它是否是你正在查找的查詢計劃。

+0

非常感謝@JakubKania。這更接近我想要做的事情。唯一的問題是數據庫在內部子查詢後將所有記錄收集到一個節點。如果它可以在採集操作之前應用相交濾波,那將是完美的。 – ablimit

+0

@ablimit我懷疑這是可能的。我能想到的唯一的另一種方式是創建一個相關的子查詢,它將使用GiST索引進行搜索,但是它會針對每行進行調用,因此您必須測量與一個預定義多邊形相交的多邊形的搜索量並對其進行比較與當前時間。另外,事實證明,GIST有int(http://www.postgresql.org/docs/9.2/static/btree-gist.html),所以(tilename,polygon)上的索引值得關注。 –