2017-06-22 98 views
2

我有一個數據庫,其中有四列,分別對應起始和結束位置的地理座標x,y。列是:IN子句中的MySQL多列

  • X0
  • Y0
  • X1
  • Y1

我對這些四列與序列X0,Y0,X1,Y1的索引。

我有一個大約一百個地理組合的列表。我將如何去有效地查詢這些數據?

我謹this SO answer的建議做這樣的事情,但它僅適用於Oracle數據庫,MySQL的不是:

SELECT * FROM my_table WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1)); 

我想有可能做的事指數?什麼是最好的方法(即:最快的查詢)?謝謝你的幫助!

注:

  • 我不能更改數據庫的模式
  • 我對100'000'000行

編輯: 代碼原封不動地竟是工作,但它非常緩慢,並沒有利用指數(因爲我們有一箇舊版本的MySQL v5.6.27)。

+0

這應該在MySQL的正常工作,你試過嗎?我看到的第一條評論說,你所關聯的問題來自5年前。 – Uueerdo

+1

只要你知道,你**可以**在MySQL中做到這一點。看到我的測試:http://sqlfiddle.com/#!9/7b5c1/1 – sorayadragon

回答

4

爲了有效地利用索引,你可以重寫IN謂詞

(x0, y0, x1, y1) IN ((4, 3, 5, 6),(9, 3, 2, 1)) 

像這樣:

( (x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6) 
OR (x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1) 
) 
+0

您的解決方案要快得多。使用我們的MySQL版本,單個查詢(100'000'000行,列表中的10個元素)在解決方案中耗時3.14秒,使用「IN」語法耗時1427秒。 – nbeuchat

+0

@GordonLinoff建議的查詢模式可能更快, 將單獨SELECT語句的結果與'UNION ALL'集合運算符連接起來。 EXPLAIN可能會以「ref」和「const」顯示查詢,而不是「範圍」。該模式肯定會使用索引。不保證它會更快,但值得測試。 – spencer7593

+0

只有一次性測試,GordonLinoff的解決方案比你的解決方案稍慢(3.96 vs 3.14秒)。這是迄今爲止不是一個嚴格的測試,但至少,這兩個選項都使用索引。 – nbeuchat

1

可以concatenate四個值轉換爲字符串,並檢查他們這樣的:

SELECT * 
FROM my_table 
WHERE CONCAT_WS(',', x0, y0, x1, y1) IN ('4,3,5,6', ..., '9,3,2,1'); 
+0

MySQL需要評估表中*每行*的CONCAT_WS函數。這可能會使用索引,但它會對索引進行全面掃描,所有100,000,000行。 – spencer7593

4

我不明白你的意思。以下查詢是有效的MySQL語法:

SELECT * 
FROM my_table 
WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1)); 

我希望MySQL使用您所描述的組合索引。但是,如果沒有,你可以這樣做:

SELECT * 
FROM my_table 
WHERE x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6 
UNION ALL 
. . . 
SELECT * 
FROM my_table 
WHERE x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1 

WHERE條款中的平等的比較將採取指數的優勢。

+0

確實,這是一個有效的語法,但需要花費很長時間才能執行。看來我們使用的MySQL版本沒有利用索引。 – nbeuchat

0

你正在做的是給在MySQL的版本正確結果的方式我機。我正在使用v5.5.55。也許你正在使用一個較舊的。請檢查。

如果您仍想在您自己的版本中解決此問題或者上述解決方案無效,請僅閱讀下一個解決方案。

我還不清楚這裏所有列的數據類型和範圍。所以我假設數據類型是整數,範圍在0到9之間。如果是這種情況,你可以很容易地做到這一點,如下所示。

select * from s1 where x0+10*x1+100*y1+1000*y2 in (4356,..., 9321); 
+0

使用這種方法,MySQL將不能在索引'(x0,x1,y1,y2)'上使用範圍掃描操作。 MySQL將在表中的100,000,000行中的每一行中的where子句中評估該表達式。 – spencer7593