2017-04-03 49 views
0

我有一個表有以下欄目:聯合索引的性能與可選的where子句

id-> PK 

customer_id-> index 

store_id-> index 

order_date-> index 

last_modified-> index 

other_columns... 

other_columns... 

我有三個單列索引。我還有一個customer_id_store_id索引,它是引用其他表的外鍵約束。

id,customer_id,store_id是char(36),它是UUID。 order_date是datetime,last_modifed是UNIX時間戳。

我想通過刪除所有索引並添加一個(customer_id,store_id,order_date)來獲得一些性能。大多數查詢將在where子句中包含這些字段。但有時store_id將不再需要。

什麼是最好的方法?在where子句中添加「store_id IS NOT NULL」或以這種方式創建索引(customer_id,order_date,store_id)。

我還經常需要通過last_modified字段(where子句包括customer_id =,store_id =,last_modified>)來查詢表。

由於我只有一個列索引,並且有數百個插入/更新表的客戶,所以索引往往會掃描超過需要的行。創建另一個索引(customer_id,store_id,last_modified)還是保持原樣?或者將此列添加到前一個索引中,使其成爲四列組合索引。但是再次order_date在這裏是不相關的,省略它可能會導致索引不能按照預期使用。

查詢對沒有多行的客戶可能使用customer_id索引的速度很快。但對於擁有大量數據的客戶來說,這並非最佳選擇。更多的時候我只需要幾天的數據。

任何人都可以請告知什麼是這種情況下最好的索引。

+2

除非您顯示您希望優化的查詢,否則幾乎不可能幫助您。話雖如此,許多單列索引通常被認爲是有害的。 –

+0

請考慮對您的問題進行編輯以提供更多信息。另外,請閱讀。 https://meta.stackoverflow.com/questions/271055/tips-for-asking-a-good-structured-query-language-sql-question/271056#271056 –

回答

1

的確,MySQL表中的大量單列索引通常被認爲是有害的。

查詢與

WHERE customer_id=constant AND store_id=constant AND last_modified>=constant 

將由索引上(customer_id, store_id, last_modified)加速。爲什麼? MySQL查詢規劃器可以隨機訪問索引到它需要檢索的第一個項目,然後順序掃描索引。同樣的指標適用於

WHERE customer_id=constant AND store_id=constant 
    AND last_modified>=constant 
    AND last_modified< constant + INTERVAL 1 DAY 

,但該索引將不會爲查詢是有用的只有

WHERE store_id=constant AND last_modified>constant 

WHERE customer_id=constant AND store_id IS NOT NULL AND last_modified>=constant 

對於首先需要(store_id, last_modified)這些查詢模式實現順序掃描索引的能力。

這些查詢模式的第二個需要兩個不同的範圍搜索。一個是something IS NOT NULL。這是一個範圍搜索,因爲它必須穿過列中的所有非空值。第二範圍搜索是last_modified>=constant。這是範圍搜索,因爲它從滿足給定條件的第一個值last_modified開始,並掃描到索引的末尾。

MySQL索引是B樹。這意味着,基本上,它們被分類到一個特定的順序。因此,索引最適合加速僅需要一次範圍搜索的查詢。所以,第二個查詢模式本質上難以滿足索引。

表可以有多個複合索引,旨在滿足多種不同的查詢模式。通常情況下,大型表的策略在實際應用中運行良好。每個索引對更新和插入都會造成一點性能損失。索引也佔用存儲空間。但是這些日子裏存儲非常便宜。

如果你想使用複合索引,以多個條件進行搜索,這些東西必須是真實的:

  1. 所有,但標準之一必須是平等的標準像store_id = constant
  2. 一個標準可以是範圍掃描標準,如last_modified >= constantsomething IS NOT NULL
  3. 必須對索引中的列進行排序,以便出現等於標準全部中涉及的列,然後列中涉及範圍掃描標準。
  4. 您可能會提到範圍掃描標準之後的其他列。但是它們構成了覆蓋指數策略的一部分(超出了本文的範圍)。

http://use-the-index-luke.com/是索引黑色藝術的一個很好的基本介紹。

+1

如果我在某些場合不需要中間部分或者我想要所有商店的數據,如果我將查詢更改爲:索引(customer_id,store_id,last_modified)是否工作:WHERE customer_id = constant AND store_id IS NOT NULL AND last_modified>常量。 – James

+0

不,不,一千次沒有。當你嘗試快速查詢時,「不是NULL」是一個臭名昭着的反模式。看我的編輯。 –

+0

太棒了!所以,我會創建(customer_id,order_date,store_id)。所有查詢都將具有customer_id,order_date和偶爾的store_id。這意味着這將在所有這些查詢中正常工作。我可能會創建(customer_id,store_id,last_modified),因爲查詢將按照該順序進行搜索。除了更多的磁盤空間,這有什麼缺點嗎?在刪除單列索引之前先創建組合索引,因爲有些不必要?如果我先刪除它們,查詢優化器將使用其他可能代價高昂的索引。 – James