2012-08-30 24 views
0

我使用下面的查詢上的相對大的表(〜2000萬行):如何使用組合索引進行昂貴的聚合查詢?

SELECT 
    MAX(`col_1`) 
FROM `table` 
WHERE 
    col_2 = X AND 
    col_3 = Y AND 
    col_4 = Z 

我已經在列組合索引COL_2,col_3和col_4和上COL_1的單獨一個,但查詢是仍然比沒有WHERE部分的相同查詢慢多個數量級。

如何使用索引來改善這方面的性能?

+0

你是否檢查過該索引是否與「解釋」一起使用?索引是否按這個確切順序包含列? – j0nes

+0

你使用什麼引擎? MyISAM或InnoDB? – Kermit

+0

引擎是InnoDB。我還有一個關於所有4列的索引,是否必須按照特定的順序? – Thomas

回答

1

由於How MySQL Uses Indexes下記載:

MySQL使用索引這些操作:

[ deletia ]

  • 要查找特定的索引列key_colMIN()MAX()。這由預處理器進行了優化,該預處理器檢查您是否在索引中的key_col之前發生的所有關鍵部件上使用了WHERE key_part_N = constant。在這種情況下,MySQL會爲每個MIN()MAX()表達式執行單鍵查找,並用常數替換它。如果所有表達式都被常量替換,則查詢立即返回。例如:

    SELECT MIN(key_part2),MAX(key_part2) 
    FROM tbl_name WHERE key_part1=10;

因此,MySQL不能使用的是您在col_1尋找MAX(col_1)當你申請一個過濾器定義的簡單指標:它必須轉而掃描所有匹配的行(雖然它可以按照col_1的降序排列,按照該簡單索引進行排序),如查詢的EXPLAIN輸出所示。

您應該使用(col_2, col_3, col_4, col_1)上的索引。

+0

謝謝,這推動了查詢時間的水平,它沒有'哪裏' 部分 – Thomas

1

您可以嘗試在第四位索引col_1,但很大程度上取決於表的結構(即單行的權重)。在col_1上計算MAX時,如果沒有WHERE,則通過索引立即可以獲得信息(只需將其保持在原來的左側即可)。

添加一個WHERE,它不再是如此。您的查詢可能已被優化。進一步的改進可能(可能)可以通過知道X,Y和Z的類型及分佈進行

(A笨例如:說col_2col_3col_4已知是在範圍(-255,+ 255 ),那麼你可以考慮添加一個額外的非規格化列,並保留(((col_1+255)*512+(col_2+255))*512+(col_3+255)),並在該索引和col_1上編制索引,甚至可以基於該索引進行集羣如果可以找到一個結果數據類型合理的內射函數,你經常在X,Y和Z上運行「精確」查詢,即沒有WHERE col_2 BETWEEN X1 AND X2東西)。

+0

感謝您的回答。在我的情況下,查詢總是「精確」,因爲col_2-4是函數的參數,而col_1是該函數運行時創建的時間戳。我想知道的是「函數最後一次使用這些參數運行的時間」。 – Thomas

+0

那麼,在這種情況下,如果參數具有足夠小的基數,則可以從中構建一個整數。我懷疑他們是整數網格座標;但是如果它們是浮點數,恐怕只有四倍索引是唯一的可能。很高興知道這是一種可能性,工作:-) – LSerni

相關問題