1.概念
對於某些業務情況,當單列索引滿足不了現實的業務,爲了提高搜索效率,就需要考慮運用於組合索引.
組合索引:即一個索引包含多個列;
2. 添加索引
ALTER TABLE people ADD INDEX `index_name` ( `column1`,`column2`,`column3`);
3.測試
建立基於departID,doctorID,scheduledTime的組合索引,執行計劃如下:
4.最左前綴索引失效問題
之前創建的IDX_MBScheding_Group的組合索引,相當於創建了(departID,doctorCode,scheduledTime)、(departID,doctorCode)、(departID,scheduledTime)這些列組合上的索引.但是因爲"mysql組合索引最左前綴"(Leftmost Prefixing)的結果.則不存在(doctorID,scheduledTime)等這樣的組合索引.
最左前綴索引有效與無效列表:
//The following queries can use the Leftmost Prefixing index:
//where後過濾字段可不按該排序
select ID,ScheduledDate from TB_MB_Scheduling where departID = 309 and doctorCode = '0003' and ScheduledTime = 'SW'
select ID,ScheduledDate from TB_MB_Scheduling where departID = 309 and doctorCode = '0003'
select ID,ScheduledDate from TB_MB_Scheduling where departID = 309 and ScheduledTime = 'SW'
select ID,ScheduledDate from TB_MB_Scheduling where departID = 309
//The following queries cannot use the Leftmost Prefixing index at all:
select ID,ScheduledDate from TB_MB_Scheduling where doctorCode = '0003' and ScheduledTime = 'SW'
select ID,ScheduledDate from TB_MB_Scheduling where doctorCode = '0003'
select ID,ScheduledDate from TB_MB_Scheduling where ScheduledTime = 'SW'
不存在(doctorID,scheduledTime)等這樣的組合索引:
從執行計劃可以看出最左前綴索引已經失效,直接進行全表掃描
- 那麼問題來了,創建的索引順序與where語句後順序是否需要一致呢?
在滿足最左前綴索引情況下,查看where語句後字段不同的排序後的執行計劃,發現:創建組合索引時字段的排序與where語句後順序是不需要一致的.
總結:最左前綴是不是失效其實就是取決於你創建索引時,哪個字段排在首位,只要你的搜索條件包含有排在首位的那個字段就能走創建的索引,即滿足最左前綴.
比如:基於(departID,doctorID,scheduledTime)創建的索引IDX_MBScheding_Group,只要where含有過濾字段departID=XXX,無論過濾字段順序先後,都走索引IDX_MBScheding_Group.
- 那麼問題又來了,怎麼才能確定合適的索引列順序呢?
5.選擇合適的索引列順序
正確的順序依賴於使用該索引的查詢,並且同時需要考慮如何更好的滿足排序和分組的需要(本小節只適合B-Tree索引;哈希或者其他類型的索引並不會像B-Tree索引一樣按順序存儲數據)
當不需要考慮排序和分組時,將選擇性最高的列放在前面通常時很好的.這時候索引的作用只是用於優化where條件的查找.
以下面查詢爲例
select * from TB_MB_Scheduling where departID = 309 and doctorCode = '0003' and ScheduledTime = 'SW'
是應該創建一個(departID,doctorCode,scheduledTime)還是顛倒一下順序?還是?
5.1 具體查詢法
可以先跑一下來確定在這個表中值的分佈情況,並確定哪個列的選擇性更高.先查看各個where條件的分支對應的數據基數有多大:
所以應該把索引列doctorCode放在前面,因爲對應的條件值doctorCode數量更小.然後根據doctorCode的條件值,查看對應的其他2列的選擇性如何:
(注:查詢結果根據你選定條件的具體值而定)
5.2 經驗法
經驗法則考慮的是全局基數和選擇性.而不是具體的某個查詢.
doctorCode的選擇性更高,所以應該將其作爲第一列.
參考來自:
1.<<高性能MySQL>>
2.http://blog.csdn.net/xtdhqdhq/article/details/17582779