2013-10-07 132 views
3

我有一張郊區表,每個郊區都有一個geom值,表示它在地圖上的多邊形。還有另一個房子的桌子,每個房子在地圖上都有一個geom值。Postgis ST_Intersects查詢不使用現有的空間索引

這兩個geom列都使用gist進行索引,而郊區表的名稱列也有索引。郊區表有8k +個記錄,而房屋表有300k +個記錄。

現在我的任務是找到一個名爲'FOO'的郊區內的所有房屋。

QUERY#1:

SELECT * FROM houses WHERE ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom); 

查詢計劃結果:

Seq Scan on houses (cost=8.29..86327.26 rows=102365 width=136) 
    Filter: st_intersects($0, geom) 
    InitPlan 1 (returns $0) 
    -> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32) 
      Index Cond: ((suburb_name)::text = 'FOO'::text) 

運行查詢了〜3.5秒,返回486條記錄。

QUERY#2:(帶_前綴ST_INTERSECTS功能明確的告訴它不使用索引)

SELECT * FROM houses WHERE _ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom); 

查詢計劃結果:(完全相同的查詢#1)

Seq Scan on houses (cost=8.29..86327.26 rows=102365 width=136) 
    Filter: st_intersects($0, geom) 
    InitPlan 1 (returns $0) 
    -> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32) 
      Index Cond: ((suburb_name)::text = 'FOO'::text) 

運行查詢花費了〜1.7s,返回了486條記錄。

QUERY#3:(使用& &運營商ST_Intersects函數之前添加一個邊界框重疊檢查)

SELECT * FROM houses WHERE (geom && (SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO')) AND ST_INTERSECTS((SELECT geom FROM "suburbs" WHERE "suburb_name" = 'FOO'), geom); 

查詢計劃結果:

Bitmap Heap Scan on houses (cost=21.11..146.81 rows=10 width=136) 
    Recheck Cond: (geom && $0) 
    Filter: st_intersects($1, geom) 
    InitPlan 1 (returns $0) 
    -> Index Scan using suburbs_suburb_name on suburbs (cost=0.28..8.29 rows=1 width=32) 
      Index Cond: ((suburb_name)::text = 'FOO'::text) 
    InitPlan 2 (returns $1) 
    -> Index Scan using suburbs_suburb_name on suburbs suburbs_1 (cost=0.28..8.29 rows=1 width=32) 
      Index Cond: ((suburb_name)::text = 'FOO'::text) 
    -> Bitmap Index Scan on houses_geom_gist (cost=0.00..4.51 rows=31 width=0) 
     Index Cond: (geom && $0) 

運行查詢了0.15 s,返回486條記錄。


顯然只有查詢#3正在從顯着提高性能的空間索引中獲益。然而,這個語法很醜陋,並且在某種程度上重複着它自己。我的問題是:

  1. 爲什麼postgis不夠智能在查詢#1中使用空間索引?
  2. 爲什麼查詢#2與查詢#1相比具有(更多)更好的性能,因爲它們都不使用索引?
  3. 任何建議使查詢#3漂亮嗎?還是有更好的方法來構建查詢來做同樣的事情?
+0

麥克指出,使用從兩個表並同時利用字符串和空間索引。它花了0.14s,並給出相同的結果集。 我也給JOIN一個去這樣: 選擇房屋。*從房子 JOIN郊區ST_Intersects(房屋。geom,suburbs.geom) WHERE suburbs.suburb_name ='FOO'; 它具有與來自兩個表的SELECT查詢相同的性能。所以兩者都可以接受。 我相信關鍵是要刪除子查詢。 –

回答

3

嘗試壓扁查詢到一個查詢,沒有不必要的子查詢:

SELECT houses.* 
FROM houses, suburbs 
WHERE suburbs.suburb_name = 'FOO' AND ST_Intersects(houses.geom, suburbs.geom); 
+0

使用兩個表中的SELECT可以同時使用字符串和空間索引。 –