2017-09-08 85 views
1

我正在研究需要運行SQL查詢以查看某些位置是否屬於由多邊形定義的轄區的應用程序。這些司法管轄區每季度更新一次,這意味着我也需要根據我檢查的日期來檢查它們。我使用mySQL函數MBRContains來幫助縮小我正在查看的轄區的範圍,使我的應用程序更容易檢查給定的點是否落入其中的任何一個。現在,我的疑問是這樣的:通過更改評估順序來減少SQL查詢的執行時間

SELECT DISTINCT t0.id FROM jurisdiction t0 
WHERE t0.beginDate <= '2017-08-05' AND t0.endDate >= '2017-08-05' 
AND MBRContains(t0.geometry,GeomFromText("POINT(48.0 -120.0)")); 

我相當肯定MBRContains是一個更昂貴的操作比檢查日期,但我還沒有與SQL多少工作,我不能確定如何使因此,管轄權將首先按日期過濾,然後針對MBRContains進行檢查。我怎樣才能做到這一點?在使用此查詢獲得相同結果時,我可以做其他優化嗎?

+0

不確定它是否是一個錯字,但這些都是不好的日期。對於一個日期字段應該是'DATE'數據類型;換另一種方法,即使你堅持使用字符串值,字符串也需要進行格式化,使得這些比較實際上是有意義的('06-08-2001'的結束日期'05-08-2017'之後,類似地'04 -08-2020'的開始日期'05-08-2017'之前) – Uueerdo

+0

@Uererdo日期和點是例子。我已經檢查過它傳遞的是正確的日期,並且正確地過濾了結果,只是查詢時間過長。 – user3726962

+0

如果您在beginDate,endDate和geometry上使用索引,它將加速您的訪問。 – hackela

回答

2

我會在(beginDate,endDate)上添加一個索引。一個索引,在兩個字段上,不是單獨的索引。

此外,如果提供的日期始終是單一日期,則將條件的日期部分更改爲'2017-08-05' BETWEEN t0.beginDate AND t0.endDate可能會進一步提供幫助(但可能不會)。

另外,在過去有類似的問題,我建議使用附加條件,使用更簡單的邊界檢查,也可以從索引中獲益;但那些通常涉及可以使用較大邊界框的情況。僞條件就像「在邊界框和邊界區域中的位置」; 「在邊界框中」使用索引消除了遠點,減少了更復雜的「邊界區域」檢查的點數。

1

如果MBRContainsGeomFromText是確定性的功能,而不是被標記爲這樣的,那麼這樣做可能會有所幫助。

確定性函數總是返回相同的輸入值。 UPPER()是確定性的,因爲它始終爲相同的輸入提供相同的輸出。這意味着如果優化器知道中間值永遠不會改變,則優化器可以創建快捷方式。

更多關於確定功能:

(現在我搜索周圍,我看到這些功能作爲數據庫的一部分提供,而不是那些你所以你不能控制它們。但是,我將這裏的答案作爲一個例子來說明如何加快調用函數的SQL。)

+0

編號'DATE(col)'是確定性的,但優化器將不會爲'WHERE DATE(col)= CURDATE()'使用'INDEX(col)'。也沒有任何其他捷徑​​。它踢。 (好吧,它只會評估「CURDATE」一次。) –

1

檢查一個範圍就像你正在做的事情一樣,不能很好地進行優化。你能得到的最好的是掃描一半的桌子。這是有問題的。

實際上,你被困在掃描。那麼WHERE什麼部分首先評估的問題就會變得很小。這是因爲取出一行比起WHERE條款中的幾乎所有函數要昂貴得多。

您是否試過geometrySPATIAL索引? 可能顯着幫助。如果是這樣,這個答案的其餘部分是沒有意義的。

前面已經提到的,「邊界框」是一個很好的嘗試:

WHERE x BETWEEN ... 
    AND y BETWEEN ... 

INDEX(x), 
INDEX(y) 

(沒有,INDEX(x,y)不起作用任何更好)

如果你談論的是一個巨大的數據集,那麼你可能需要一個more complex solution