2013-06-03 71 views
1

我有一個表:爲什麼MySQL不使用索引?

CREATE TABLE `ais`.`last_location` (
    `timestamp` timestamp NOT NULL default '0000-00-00 00:00:00', 
    `message_type` tinyint(4) NOT NULL default '0', 
    `repeat_indicator` tinyint(4) NOT NULL default '0', 
    `mmsi` int(11) NOT NULL default '0', 
    `navigation_status` tinyint(4) NOT NULL default '0', 
    `rot` tinyint(4) NOT NULL default '0', 
    `sog` smallint(6) NOT NULL default '0', 
    `position_accuracy` tinyint(4) NOT NULL default '0', 
    `longitude` int(11) NOT NULL default '0', 
    `latitude` int(11) NOT NULL default '0', 
    `cog` smallint(6) NOT NULL default '0', 
    `hdg` smallint(6) NOT NULL default '0', 
    `time_stamp` tinyint(4) NOT NULL default '0', 
    `maneuver_indicator` tinyint(4) NOT NULL default '0', 
    `spare` tinyint(4) NOT NULL default '0', 
    `raim_flag` tinyint(4) NOT NULL default '0', 
    `sotdma_sync_state` tinyint(4) NOT NULL default '0', 
    `sotdma_slot_timeout` tinyint(4) NOT NULL default '0', 
    `sotdma_slot_offset` smallint(6) NOT NULL default '0', 
    PRIMARY KEY USING BTREE (`mmsi`), 
    KEY `Index_2` (`timestamp`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;" 

我要查詢解釋:

EXPLAIN SELECT * 
FROM last_location 
WHERE `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:30:00' 

1, 'SIMPLE', 'last_location', 'range', 'Index_2', 'Index_2', '4', '', 83, 'Using where' 

EXPLAIN SELECT * 
FROM last_location 
WHERE `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:40:00' 

1, 'SIMPLE', 'last_location', 'ALL', 'Index_2', '', '', '', 478, 'Using where' 

誰能告訴我搜索到11:30和11:40之間的區別?當使用11:30時,一切都看起來沒問題,我想?但是在使用11:40時它不再使用索引了?

+1

推測mysql根據它在表上的統計數據計算出它在這種情況下不值得使用索引。執行時間有重大差異嗎? – nos

+0

[MySql中的BETWEEN操作索引]的可能的重複(http://stackoverflow.com/questions/2175163/index-for-between-operation-in-mysql) – Vyktor

+0

表中有多少行? – ankurtr

回答

1

如果統計信息表明您將訪問整個表以獲取匹配行,則查詢計劃人員保留忽略索引的權利。

原因在於,按照索引所指示的順序在磁盤頁面上來回跳動,而在過濾所需的行時,依次逐個讀取磁盤頁面會更便宜。

+0

我的問題太快了,數據庫在這個時候填滿了,現在這個索引現在一直在使用(我所見過的)。結論是,MySQL正在自我優化,結果索引不被少量的行使用。 – ralphvn86

1

索引掃描每個記錄需要更多I/O(因爲它需要通過嵌套循環訪問表本身,通常是隨機訪問I/O),但允許使用更少的記錄(只有那些滿足可靠條件的記錄) 。

表掃描不可避免地掃描整個表,但每個記錄的I/O需要少得多(這是對一個.MYD文件的順序掃描)。

MySQL的優化器意識到這一點,並可能根據可選狀態的選擇性選擇一個或另一個訪問路徑:更多的選擇性條件可能從索引掃描中受益,更少的選擇性對於全表掃描更有效。

這就是你正在觀察的。

注意,優化的解決方案可能是低效的,特別是如果你有一些特定的數據分佈,I/O子系統的佈局等,您可以強制索引掃描:

SELECT * 
FROM last_location FORCE INDEX (Index_2) 
WHERE `timestamp` BETWEEN '2013-01-01 12:00:00' AND '2013-06-03 11:40:00' 

如果您認爲該指數更高效。

+0

我想我明白了不同的行爲,MySQL只是決定索引是否使用有趣,或者不是。 – ralphvn86