假設一高頻查詢以下
SELECT * FROM user WHERE area='amoy' AND sex=0 ORDER BY last_login DESC limit 30;
如何創建索引?描述考慮的過程mysql
user表以下:
初始化100W條數據,其中,area要經過IP查詢生成,sex爲 0,1 隨機sql
CREATE TABLE user
(id
int(10) NOT NULL AUTO_INCREMENT COMMENT '自增編號',username
varchar(30) NOT NULL DEFAULT '0' COMMENT '用戶名',password
varchar(30) NOT NULL DEFAULT '0' COMMENT '密碼',area
varchar(30) NOT NULL COMMENT '地址',sex
int(10) NOT NULL COMMENT '性別1,男;2,女。',last_login
int(10) NOT NULL COMMENT '最近一次登陸時間戳',
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=892013 DEFAULT CHARSET=latin1性能
最終個人索引
(last_login,area)mysql索引
user表
沒有任何索引的查詢相關日誌:
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.56s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.59s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.58s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
共花費時間:5.66s測試
創建索引area:
ALTER TABLE user
ADD INDEX index_area
(area
) ;
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.10s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.11s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.20s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
共花費時間:0.66s
可見,創建area之後對性能的影響是巨大的(5.66/0.66 約爲8.5758倍)
刪除索引:ALTER TABLE user
DROP INDEX index_area
;
刪除area索引起現時間又變成了0.57s日誌
創建last_login索引:
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.09s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.51s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
共花費時間:0.87s
一樣可以提高性能(5.66/0.87 約爲6.5057倍)code
創建sex索引:
ALTER TABLE user
ADD INDEX index_sex
(sex
) ;
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.89s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.88s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.86s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.88s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
共花費時間:8.73s
一樣可以提高性能(5.66s/8.73 約爲0.6483倍)效率反而下降了??求解?
創建這個sex索引還不如不建。排序
刪除索引:
ALTER TABLE user
DROP INDEX index_sex
;
發現時間又變成了0.57s左右,索引
創建兩個單獨的索引:
ALTER TABLE user
ADD INDEX index_area
(area
) ,
ADD INDEX index_last_login
(last_login
) ;get
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.09s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.33s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.21s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.28s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.67s
發現創建兩個單獨的索引還不如只創建一個索引
刪除索引:
發現時間又變成了0.57s左右,
創建一個的聯合索引:
ALTER TABLE user
ADD INDEX index_last_login_area
(last_login
,area
) ,
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
額,第二條數據這是怎麼了,我測試了5次都在這附近晃悠哈!
這尼瑪,找對索引啦!就該這麼創建,查詢不出來須要的時間啦!估計就是咱們須要的索引啦!!!!
刪除索引:
發現時間又變成了0.57s左右,
創建一個的聯合索引:
ALTER TABLE user
ADD INDEX index_sex_last_login_area
(sex
,last_login
,area
)
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.18s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.17s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.81s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
sex怎麼老是你在拖後腿啊!把你調整到索引的最後一個吧!
刪除索引:
發現時間又變成了0.57s左右,
創建一個的聯合索引:
ALTER TABLE user
ADD INDEX index_last_login_area_sex
(area
,last_login
,sex
)
SELECT * FROM user WHERE area='美國ATT用戶' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='泰國' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='臺灣省臺灣大寬頻' AND sex=0 ORDER BY last_login DESC limit 30; 0.50s
SELECT * FROM user WHERE area='美國弗吉尼亞州' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='德國奔馳汽車' AND sex=0 ORDER BY last_login DESC limit 30; 0.05s
SELECT * FROM user WHERE area='臺灣省中華電信' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
SELECT * FROM user WHERE area='韓國' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='拉美地區' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='美國紐約(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='印度尼西亞' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
綜上所述:1.創建索引不必定可以加快查詢效率如sex這種給重複次數特別多的列增長索引如sex這種會下降查詢效率,具體的緣由有待查找
2.給重複次數比較少的列增長u謳吟仍是可以大幅度提升效率
3.給where和orderby以後的字段添加索引纔會加快查詢效率
4.爲每個列單獨創建索引,不能將索引的效率最大化,應該使用索引合併策略,即根據查詢條件,創建聯合索引
5.聯合索引的順序問題:將選擇性高的索引放到前面
6.根據資料創建索引意味着索引按照最左列進行排序,而後事第二列,以此類推。如(last_login ,area)就會按照last_login進行排序,而後纔是area
7.根據此次的這個查詢條件來講最好的索引是:ALTER TABLE user
ADD INDEX index_last_login_area
(last_login
,area
)。