2013-04-24 20 views
0

我有一個類似這樣的表(我已經刪除了很多字段以方便解釋) 。訂單ID是用來顯示一排多麼重要的是一個INT非唯一值(和我通過它順序返回數據時)Mysql的EXPLAIN顯示'使用filesort',如果我選擇多個列,但'使用索引'如果不是

CREATE TABLE `my_images` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `orderId` int(11) NOT NULL, 
    `slug` varchar(50) NOT NULL, 
    `imageFilename` varchar(255) NOT NULL, 
    `thumb200` varchar(255) NOT NULL, 
    `thumb600` varchar(255) NOT NULL, 
    `md5hash` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `orderId` (`orderId`), 
    KEY `thumb600` (`thumb600`), 
    KEY `slug` (`slug`), 
    KEY `multiple_1` (`md5hash`,`orderId`,`thumb200`,`thumb600`), 
    KEY `md5hash` (`md5hash`), 
    KEY `thumb200` (`thumb200`), 
    KEY `thumb200_2` (`thumb200`,`orderId`), 
    KEY `orderId_2` (`orderId`,`thumb600`,`thumb200`), 
    KEY `thumb600_2` (`thumb600`,`orderId`), 
    KEY `thumb600_3` (`thumb600`,`orderId`), 
    KEY `orderId_3` (`orderId`,`thumb600`), 
) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

是 - 有很多指標覆蓋的orderId的。它是一個嘗試解決當前問題的組合,也是因爲我在WHERE語句中使用這些字段。

無論如何,如果我運行此命令:

explain SELECT id FROM my_images 
ORDER BY orderId asc 

它輸出這個( 「使用索引」)

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE my_images index NULL orderId 4 NULL 174553 Using index 

預計 - 訂單ID是一個索引。

,但如果我這樣做:

explain SELECT id, thumb600, imageFilename, slug FROM my_images 
ORDER BY orderId asc 

它輸出這種(使用文件排序):

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE my_images ALL NULL NULL NULL NULL 174553 Using filesort 

和古怪如果我這樣做

explain SELECT id, md5hash FROM my_images 
ORDER BY orderId asc 

它說:「使用索引;使用filesort「

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE my_images index NULL multiple_1 775 NULL 174553 Using index; Using filesort 

我注意到的原因是因爲我看到一個緩慢的查詢,這基本上是'orderId限制4000,3'的select(一堆字段)順序,這需要很長時間,並且在運行explain命令後看到了。什麼可以做,所以它總是使用索引?我是否必須創建一個包含我選擇的所有字段的索引?如果這樣的話,索引中的字段順序很重要?

回答

3

如果您選擇索引未覆蓋的列,引擎將不得不進行表查找以獲取這些列的值。

由於您選擇整個表(不使用WHERELIMIT),順序掃描表然後對其進行排序,而不是執行大量關鍵查找操作會更快。

此外,MySQL不能進行晚行查找,這意味着即使在使用索引時,它在計算偏移量之前始終查找表。

如果你是一個非PK場中的InnoDB表排序,試試這個:

SELECT i.* 
FROM (
     SELECT id 
     FROM my_images 
     ORDER BY 
       orderId 
     LIMIT 4000, 3 
     ) q 
JOIN my_images i 
ON  i.id = q.id 

請參閱本文中我的博客解釋:

+0

感謝您的這一點。 (順便說一下,我使用的是WHERE和LIMIT,但只是爲了讓這裏更容易閱讀而忘了) – slycat 2013-04-25 11:11:39

+0

你不知道這有多大的幫助。瘋了,試圖找出爲什麼一個有很多行的mysql表甚至沒有索引也不快。你的博客文章解釋得很好。 – slycat 2013-04-25 11:30:45

2

添加索引訂單ID,然後將您想要的列作爲索引

的問題是,當你添加其他列則文件排序就像即時貼它將不得不回憶他們

但是如果你在索引中的列(它必須是一個索引4-6列)作爲每個查詢將只使用一個索引。列將繼續前行

相關問題