2016-04-15 75 views
1

我有以下表格是postgres(postgis)。這兩個表有1,不同類型的字符第2,第3列(9000)和類型「幾何」的第4列(包含點幾何(緯度,經度)):加入兩張表

Table1 
Column1  Column2    Column3 the_geom 
Oklahoma  numericalValue1  719  NULL 
Oklahoma  geometry   NULL  (34.6,95.3) 
Oklahoma  liesIn    America NULL 

Table2 
Column1  Column2   Column3  the_geom 
Mississippi liesIn    America  NULL 
Mississippi geometry   NULL  (32.7,-89.53) 
Mississippi numericalValue2 15.3  NULL 

我想運行下面的查詢在表1和表2上執行空間連接。問題中顯示的表1和表2是玩具表,在我的實際數據集中,它們每個包含100萬行。當我運行下面給出的查詢時,我發現我的查詢需要很長時間(超過10小時)才能運行。有人可以建議,如果有什麼方法可以通過重新構建查詢來優化查詢。

select * from Table1 s1, Table1 s2, Table1 s3, Table2 s4, Table2 s5, Table2 s6 where 
s1.column2='numericalValue1' and  
s2.column2='geometry' and 
s3.column2='liesIn' and 
s1.column1=s2.column1 and 
s2.column1=s3.column1 and 
s4.column2='liesIn' and 
s5.column2='geometry' and 
s6.column2='numericalValue2' and 
s4.column1=s5.column1 and 
s5.column1=s6.column1 and 
ST_DWithin(s2.the_geom, s5.the_geom, 5) 
order by (cast(s1.column3 as double precision)+cast(s6.column3 as double precision)) 
limit 1; 
+1

這是一個可怕的數據庫設計。難怪你正面臨性能問題。數據庫是關於彼此相關的實體,例如國家和國家,每個國家都有自己的屬性。所以你應該有一個國家表格和一張州表格,每個州的記錄都會指向一個國家,有一個位置等等。然而,你有一件由三件事組成的「事物」,它們的組合構成了一個虛擬記錄的屬性,再加上它的適當位置。你甚至有兩次。改變你的數據模型,一切都會好的。 –

回答

2
  1. 交換軸順序,使您的幾何形狀(XY)或(長LAT)
  2. 如果你沒有梗概空間索引,然後如何添加一個調查
  3. 我假設你正在使用SRID = 4326或EPSG:4326,它有度數單位。所以5000萬的距離是不合邏輯的,並且會做很長時間的交叉連接。嘗試使用更小的距離,例如0.01度,或者使用geography類型來調查使用線性距離或其他技巧。
+0

感謝您的回答。 ST_DWithin用於距離的度量單位是米。正確?如果我錯了,請糾正我。我還使用了GIST索引,交換軸順序,使距離= 50000(相當於50公里)。仍然postgres需要很多時間 –

+0

@JannatArora如果你想使用ST_DWithin的度量距離,你可能想調查'geography'類型。這通常是一個棘手的細節,因爲並不是每個人都有一個解決方案(例如更改數據庫類型,更改SRID,創建地理索引等) –

+0

謝謝,是否可以將數據類型從幾何到地理,如果是的話,怎麼樣? –

1

添加到@ MikeT的回答,首先確保您有column2/predicate兩個表上subject,還有一個是指數。

我想說,100萬行不是那麼多,即使是順序掃描也會在幾秒鐘內完成。如果一個查詢花費的時間超過了1-2分鐘(更不用說10個小時了!),我們有充分的理由相信查詢中的某些內容是關閉的(就像在這種情況下,正如Mike所說的,s2和s5之間的虛擬交叉連接)十億個元組),或者查詢需要丟失索引。

我發現使用連接非常有用(與where子句中的所有連接條件相反),使調試查詢更容易。例如,下面的查詢與您的查詢完全相同,但您可以輕鬆地註釋s1,s3,s4和s6上的連接以嘗試隔離並查明問題。

select * 
from Table1 s2 
join Table2 s5 on (ST_DWithin(s2.the_geom, s5.the_geom, 50000000)) 
join Table1 s1 on (s1.subject=s2.subject and s1.column2='numericalValue1') 
join Table1 s3 on (s2.subject=s3.subject and s3.column2='liesIn') 
join Table2 s4 on (s4.subject=s5.subject and s4.column2='liesIn') 
join Table2 s6 on (s5.subject=s6.subject and s6.predicate='numericalValue2') 
where s2.column2='geometry' and s5.column2='geometry' 
order by (cast(s1.column3 as double precision)+cast(s6.column3 as double precision)) 
limit 1