2013-10-28 26 views
0

我正在學習如何使用索引進行適當的查詢優化。比方說,我有一個包含各種產品細節的巨大產品列表,例如價格,類別,購買數量,平均評論等等。當有多個「where」條件時,我瞭解到,最好是按照它們出現的順序在任何「where」條件下放置多列索引。如何使用「where」子句中的用戶定義參數優化查詢?

但是,如果有太多的查詢用於不同的目的,並且用戶需要選擇如何過濾產品表,那麼我很難弄清楚如何擴展它。例如,用戶可以瀏覽產品WHERE rating > 4 AND purchases > 100,或者它可以是WHERE category = 'x' AND price < 100 AND price > 20。如果選擇要過濾的列是隨機的,那麼適當的多列索引如何工作?

回答

1

我瞭解到,無論您的「where」條件如何,最好是按照它們出現的順序放置多列索引。

你學到了......不太正確。

外觀WHERE子句中的次序是沒有意義的,因爲優化是自由以任何邏輯上有效的方法來評估的條件,受試者過程中括號和邏輯運算符的(ANDOR等)中的表達。

多列索引中列的順序很重要,因爲從左到右,一旦在where子句中未提及的索引中遇到列,沒有更多指向該索引的右側可以使用。

如果索引3列(a,b,c),並且查詢爲WHERE a = 1 AND c = 6,那麼優化器將只能使用該索引中最左邊的「a」列值,而不是「c」。

在這種情況下,它可能會仍然選擇使用該索引來查找行其中,a = 1,然後掃描所有這些確定的行只有那些有C = 6

你可以想像一個多列索引作爲多維數組。如果沒有一個已知的值或範圍需要匹配第一列(a),那麼第二列(b)的值是無意義的無序數據混亂,因爲它們按照「a」組排序。 ..你必須迭代每個「a」來找到匹配的「b」值,並遍歷每個「a,b」以找到匹配的「c」值。由於在上面的示例中,由於未指定「b」值,所以「c」值的排序對於優化查詢而言是無意義且無法訪問的(儘管列表SELECT中的每列都可用在單個索引中,優化器可以掃描索引而不是掃描整個表格,將其視爲「覆蓋索引」,通常比全表掃描更好,但仍不理想)。

如果您的WHERE子句包含兩個列,每個列都單獨編制索引,優化器將檢查索引統計信息並嘗試使用最有可能產生最少匹配的那個列表...如果「a」和「c 「每個都有一個單獨的索引,並且索引統計表明」c「(高基數)有許多值,但對於」a「(低基數)只有少數值,優化器通常會使用」c「找到匹配的行,然後掃描所有這些行以獲得所需的「a」值。

或者,它可能會嘗試使用兩個索引的聯合,以精確識別哪些行滿足這兩個條件。

這兩種策略都不是最佳選擇,但仍然遠勝於全表掃描,因此建議您至少應將每個可獨立搜索的列作爲索引中最左邊的列。也就是說,可以自行查詢的任何列,WHERE子句中不包含其他列,並返回合理大小的結果集。如果結果集的大小不合理,您可能希望限制用戶在應用程序中搜索其他屬性。

WHERE category = 'x' AND price < 100 AND price > 20的情況下,較好的指數是(類別,價格)而不是(價格,類別),但這不是因爲WHERE條款中的表達式的排序。這是因爲類別是平等測試,但價格是一個範圍。 WHERE price < 100 AND price > 20 AND category ='x'是等價的,並且(類別,價格)仍然是適當的指數 - 因爲指數按第一列排序,然後在第一列的每個值內按第二列的值排序,然後在每個第一,第二)對,它們按第三列中的值排序,ad infinitum ...因此(類別,價格)服務器直接轉到category ='x'的所有行,並在該分組內索引中,引用的行已經按價格排序,因此只需在索引的類別「x」內選擇價格範圍。最佳。 (價格,類別)索引需要檢查範圍內的所有價格,然後欺騙所有這些類別的價值。該索引仍然可以使用,但根據條件,優化器仍然可以選擇掃描整個表格。

如果向WHERE子句添加第三​​條標準,但未遵循索引,則將遵循相同的路徑,但服務器將掃描已標識的行以找到具有非索引列所需值的匹配項。再次,取決於您的業務需求,這不是最理想的,但通常是可以接受的 - 這對確定這個問題的正確答案起着作用。

每個索引需要的空間和資源,因爲每次插入,更新和刪除,要求服務器進行必要的更改 - 權然後 - 爲每個被修改表中受影響的索引。請注意,如果您有關於(a,b)或(a,b,c)等的索引,則(a)上的單獨索引通常被認爲是浪費空間,因爲索引(a,...任何其他...)也將作爲(a)的索引。

EXPLAIN SELECT進行實驗(其也支持INSERT/UPDATE/DELETE如MySQL的5.6的)和真正understanding its output是用於理解索引是如何工作的不可或缺的工具。 MySQL的5.6還支持optimizer tracing,它給你的優化器如何理解您的查詢,它考慮的各種計劃,但估計每一個計劃的成本詳細的輸出,以及它是如何到達的如何執行特定查詢的決定。

+0

非常感謝您的解釋。雖然我明白其中的一些,但我必須承認,其中一些仍然凌駕於我的頭上。當我有空時,我將不得不閱讀EXPLAIN輸出頁面,然後查看MySQL書籍中的優化章節。再次感謝。 –

+0

謝謝。請考慮接受答案或讓我知道是否有我可以澄清的要點。 –

相關問題