2012-04-15 23 views
7

我有一個非常簡單的查詢:我簡單的MySQL查詢不使用索引

SELECT comments.* 
    FROM comments 
    WHERE comments.imageid=46 

這是我的表:

CREATE TABLE IF NOT EXISTS `comments` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `imageid` int(10) unsigned NOT NULL DEFAULT '0', 
    `uid` bigint(20) unsigned NOT NULL DEFAULT '0', 
    `content` text CHARACTER SET utf8, 
    `adate` datetime DEFAULT NULL, 
    `ip` int(10) unsigned DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `ids` (`imageid`) USING BTREE, 
    KEY `dt` (`adate`) USING BTREE 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12 ; 

但MySQL不能在這個簡單的查詢使用索引。這裏是解釋結果:

id select_type  table type possible_keys key  key_len  ref  rows filtered Extra 
1 SIMPLE comments ALL  ids  NULL NULL NULL 4 75.00 Using where 

雖然我改變查詢到這個,Mysql可以使用索引。爲什麼? :

SELECT comments.id 
    FROM comments 
    WHERE comments.imageid=46 

這裏的解釋:

id select_type  table type possible_keys key  key_len  ref  rows filtered Extra 
1 SIMPLE comments ref  ids  ids  4 const 4 100.00 Using index 
+0

它不是*「但MySql **不能**使用索引」*。它是:「但MySql **不會**使用索引」。 'possible_keys = ids'和'key = NULL'表明使用索引被優化器檢查並被拒絕。全表掃描被認爲是更快 - 它可能是在你的情況。 – 2012-04-15 09:54:13

回答

6

我想你已經在「意見」表幾行,這就是爲什麼MySQL是做了充分的表掃描,而不是在第一個查詢中使用索引。據估計,全表掃描的成本可能低於首次匹配索引,然後查找行。

在您的第二個查詢中使用了索引,因爲可以直接從索引獲取查詢的所有列('id'列),而無需在匹配索引後查找表格行。這是「使用索引」額外信息的含義。

嘗試在'comments'中使用大量的行MySQL仍然使用全面掃描,我認爲這將是一個奇怪的行爲。事實上,我已經在MySQL 5.1版本中測試了完全一樣的東西,並且即使行數很少,它也總是使用「索引」。

+0

謝謝你,你是對的! ;) – MscEliot 2012-04-15 13:05:37

1

第二個查詢是一個索引覆蓋查詢。請求的全部信息可以從索引中讀取(因爲主鍵是InnoDB中的任何二級索引的一部分)。

在第一個查詢中,MySQL必須從索引讀取PK,然後讀取行。因爲表的行數很少,所以優化器決定如果它直接讀取行並放棄不匹配的行,速度會更快。