mysql 多列索和order by

多列索引的select * where * order by * 查詢條件索引很難建立,需要不斷調試,最後找出規則:


三原則:

1. 將經常要查詢的字段放到多列索引的前面

2. 將要進行等值查詢的字段放到多列索引前面

3. order by field的列放到多列索引的最後


以下是測試


先來一張表: 

CREATE TABLE IF NOT EXISTS `article` ( 

`id` int(10) unsigned NOT NULL AUTO_INCREMENT, 

`uid` int(10) unsigned NOT NULL, 

`category_id` int(10) unsigned NOT NULL, 

`views` int(10) unsigned NOT NULL, 

`comments` int(10) unsigned NOT NULL, 

`title` varbinary(255) NOT NULL, 

`content` text NOT NULL, 

PRIMARY KEY (`id`) 

); 

 

再插幾條數據: 

INSERT INTO `article` 

(`uid`, `category_id`, `views`, `comments`, `title`, `content`) VALUES 

(1, 1, 1, 1, '1', '1'), 

(2, 2, 2, 2, '2', '2'), 

(1, 1, 3, 3, '3', '3'); 

 

需求: 

查詢category_id爲1且comments大於1的情況下,views最多的uid。 

 

先查查試試看: 

EXPLAIN  SELECT uid FROM `article` WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1; 

 

看看部分輸出結果: 

 

 

很顯然,type是ALL,即最壞的情況。Extra裏還出現了Using filesort,也是最壞的情況。優

化是必須的。 

 

嗯,那麼最簡單的解決方案就是加索引了。好,我們來試一試。查詢的條件裏即where之

後共使用了category_id,comments,views三個字段。那麼來一個聯合索引是最簡單的了。 

 

ALTER TABLE `article` ADD INDEX x ( `category_id` , `comments`, `views` ); 

 

結果有了一定好轉,但仍然很糟糕: 



type變成了range,這是可以忍受的。但是extra裏使用Using filesort仍是無法接受的。 

但是我們已經建立了索引,爲啥沒用呢? 

 

這是因爲按照BTree索引的工作原理,先排序category_id,如果遇到相同的category_id則再

排序comments,如果遇到相同的comments則再排序views。當comments字段在聯合索引

裏處於中間位置時,因爲comments  >  1條件是一個範圍值(所謂range),MySQL無法利用

索引再對後面的views部分進行檢索,即range類型查詢字段後面的索引無效。 

 

那麼我們需要拋棄comments,刪除舊索引DROP INDEX x ON article; 

 

然後建立新索引:ALTER TABLE `article` ADD INDEX y ( `category_id` , `views` ) ; 

 

接着再運行查詢: 

 

 

可以看到,type 變爲了ref,Extra中的Using filesort也消失了,結果非常理想。

http://hi.baidu.com/jqxw4444/item/e3cf91393fa89f9bb80c0388


發佈了37 篇原創文章 · 獲贊 12 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章