2013-06-03 103 views
1

我是MySQL的新手,我需要在現有表(其中大約包含200K行)上添加索引。綜合索引

Table mytable: (id:integer, created_time:timestamp, deleted_time:timestamp) 

我有2個查詢,其需要從索引中獲益:

select s.id from mytable s 
where s.completed_time is not null 
and s.completed_time < ? 
and (s.deleted_time is null 
    or s.deleted_time >= ?); 

和:

select s.id from mytable s 
where 
    s.completed_time is not null 
and (
    (s.deleted_time is not null 
    and s.deleted_time >= ? 
    and s.deleted_time < ?) 
or (s.completed_time >= ? 
    and s.completed_time < ?)) ; 

我正在考慮引入的多列索引(上completed_time和deleted_time) 但是,我不確定條件「s.completed_time是否爲空」與使這些查詢使用組合索引的條件相匹配。

  • 你對什麼是最好的(複合索引或2個索引)有什麼想法嗎?我試圖用「解釋」來弄清楚什麼是最好的,但我不確定如何解釋結果。

  • 更一般地說:對於在(column1,column2)上有一個複合索引的表,我知道只對column2進行過濾不會使用索引。 但是,如果我引入了像(column1> MIN_VALUE)這樣的虛擬條件,或者(column1不是null),如果這樣做是正確的呢?

謝謝!

+1

我注意到這兩個列允許空值,這是你將要改變的,因爲它會對你的索引產生負面影響,更新那些空值設置爲空白時間戳= 0的表,將字段更改爲非空,並且我會推薦一個單獨的複合索引,否則測試兩者並查看優化器路徑(使用解釋)和結果速度進行比較。 –

回答

1

假設你提到的兩個查詢將被「頻繁」使用,我會建議一個複合索引與兩列不同的索引。

正如你所知道的,查詢在兩列上搜索可能有時使用兩個單獨的索引(粗略地)將這兩個索引合併爲一個。但是這是次優的,並且在性能方面有成本。

反之,如果最左側的列都參與了SEACH條件只能用一個綜合指數,或as the manual puts it

MySQL能使用多列索引爲測試所有 列的查詢在索引,或查詢該測試只是第一列中, 前兩列,前三列,依此類推

至於您建議的黑客(引入虛擬條件,以便能夠使用該指數),這可能工作,但我寧願建議僅在column2上創建第二個索引(除了在(column1, column2)上的雙列索引)。這是一個(次要的)成本,但是更加優雅和可重用。

至於擺脫NULL值的建議,我強烈反對。使用0時在Secunically方面不正確。 0表示「零」,NULL表示「沒有值」。你所有的測試都需要考慮這個特殊的價值,而IS NULL是標準的,並且隨處可見。在某些情況下也是不切實際的(嘗試插入0SQL_MODE='TRADITIONAL')。另一方面,性能增益是可疑的(我相信這主要是基於錯誤的假設,即NULL的值未被編入索引)。如果存在這樣的索引,那麼驗證像s.completed_time IS NOT NULL這樣的查詢將命中索引是容易的。

+0

非常感謝您的詳細解答,這真的很有幫助! – kiv

1

提供您擺脫用戶提到的空值。組合索引可能適用於第一個查詢。

但第二個查詢索引可能無法正常工作。 - 因爲它在你的索引列之間有一個OR。

通常按照索引中最左邊的列和該順序。

我建議創建單獨的索引。雖然它有一個開銷(可能是)http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html