mysql的索引並非很好總結,因此平常工做中你們應該多使用 explain 來優化本身的查詢和索引,作到用最少的索引來配合最高效的查詢語句完整業務需求,這裏我總結一些平日裏遇到的比較多變的索引問題:組合索引的設計問題, order by 如何利用索引mysql
應用場景:頻繁對多列進行聯合檢索,可作組合索引算法
例如咱們建立了 name email nick 的組合索引 name_email_nick
sql
要想使用此索引則必須遵循 最左前綴 原則,說的簡單些就是 檢索條件集 能夠從左到右的優先級次序匹對 組合索引的列序shell
能夠看出組合索引實際上是爲每個子列創建的索引,而後以 seq_in_index 的位序鏈接在一塊兒,當你想讓本身的查詢能啓用此索引,則最基本的一條就是最左前綴,按位序能夠依次知足,中間不存在位序間斷
函數
拿此例來講,左前綴的組合方式有(注意,這裏是條件集的最終拼接結果,並非條件位序):優化
1 1,2 1,2,3
而
spa
2 3 2,3
都不知足最左前綴原則設計
實例:
code
name 使用一個
索引
name email 使用兩個
name email nick 使用三個
再次強調最左前綴與檢索條件的書寫順序無關,只要能知足從左開始不間斷的知足組合索引的子列位序便可
如上圖所示,檢索條件的位序雖然與組合索引的不一樣,但並不影響
最左前綴:檢索條件集合能夠按組合索引列序無間斷的排列出連續的位序列,則可以使用此索引,不然沒法使用此索引
如上圖所示,檢索條件只有 email 和 nick,沒法有序的組成複合組合索引 name email nick 的不間斷序列,缺失 name 位序,因此沒法使用索引
加上 name 便可使用
這個比較容易理解,mysql 會優先使用 精確度高 的索引,由於每次查詢只能使用一個索引,因此這裏會有擇優算法
雖然檢索條件符合 primary key 和 name_email_nick 的組合索引使用條件,但主鍵能夠精準定位一條記錄,因此會使用 主鍵 而非 組合索引列,這裏也再次證實 檢索條件的位序和索引位序沒什麼關係
組合索引的本質實際上是mysql爲每組合列各添加索引,而後用位序標定他們,組合索引其中的某列索引 和 爲此列單獨添加的普通索引本質上沒有區別,以下:
我先添加的 name_email_nick 組合索引
我再爲 name 列單獨添加一普通索引
我刪掉 name_email_nick 組合索引而後再添加它,這樣就至關於 普通的 name 索引時序先於 含有 name 的組合索引了
由於個人查詢條件只有 name,因此對普通索引 name 和 組合索引 name_email_nick 來講他們所能定位的資源精確度是相等得,然後普通索引 name 與 組合索引中的 name列索引此時屬於對等,因此 mysql 就按照誰先建立的就使用誰,此時若是使用 name_email_nick 其實也只是使用其中的 name 列索引,和咱們後來添加的 name 的普通索引本質上沒有任何區別
網上不少博文說若是檢索中有使用 order by 進行檢索時,在 order by 列上加索引就會被啓用,但據我實測,order by 會使用索引只有如下幾種狀況
首先明確,每一次的檢索 mysql 只會選用一個索引
一、當 order by 與 limit 結合時也會有可能啓用索引,是有可能,由於 limit 其本質上是在我 order by 的結果集上作範圍查詢,但也是有限定範圍的,當你的 limit 跨度太大mysql仍然不會使用索引,由於代價幾乎與Using filesort對等了
二、 還有一種狀況就有些沒邏輯了:當 select 的字段與 order by 字段徹底吻合時會使用索引......這點我也不知道怎麼講,但 select col from table order by col;真的會使用 col 的索引,即使你不與 limit 聯合使用
三、至於不少人說在 order by 做用的列上加索引就會被啓用,那應該是他們的sql中在 where 條件裏有 相同列 而已,真正的索引是在 where 裏被啓用而不是 order by
索引創建以下
網上不少博文說 order by 所做用的列若是有索引便會啓用,實際上是不許確的,他們得出的結論實際上是被 where 條件中的列索引影響了
但若是你只是選擇讀取與order by 一致的列則能夠啓用索引
那怎樣在平常較爲廣泛的查詢中優化 order by 呢,簡單,在 order by 做用的列上加索引後 使用 limit 作輔助查詢,但這個範圍不能太大,不然索引和遍歷整張表沒什麼區別了,這也是分頁的精髓所在,由於 limit 也是一範圍,會使用 BTREE 索引作範圍查詢
感受與where聯用不聯用沒什麼要說的,你只要記住mysql每次查詢時只會使用一個索引,若是where中啓用索引了order by 即使和 limit 聯合也會使用 Using filesort 了
經常使用索引方式分爲 HASH 索引 和 B-TREE 索引
HASH 索引即散列索引,經過散列函數準確的定位出地址,僅適用於 MEMORY 引擎的的表,是無序的,經過 HASH 函數計算出其在內存中的位置,因此只能作精確的=值查詢,沒辦法高效的作範圍查詢。
B-TREE 索引則是有序的,適合 MyISAM InnoDB等引擎,能夠作=值,範圍(>, <, >=, <=, between, in,limit),但不支持 not in, <> 等查詢,由於不等查詢確定會遍歷全表,只有遍歷到最後一條記錄時我才能肯定本表中還有無與條件相符的記錄。
一、索引不做用於存在 NULL 值的列,因此建議你們在定義列時指定 NOT NULL DEFAULT val
二、索引不做用於參與函數運算的列 , 即使 BIRTHDAY 上加了索引,但函數做用在此列上索引失效
SELECT * FROM TABLE WHERE BIRTHDAY >= UNXI_TIMESTAMP('1990-03-07');
三、索引能夠作 等值 範圍 查詢,不可作不等查詢
/*沒法啓用索引*/ SELECT * FROM TABLE WHERE ID <> 1; SELECT * FROM TABLE WHERE ID NOT IN(1, 3, 5, 7);
四、like 作模糊查詢時
/*可以使用索引*/ SELECT * FROM TABLE WHERE `name` LIKE 'sallen%'; /*不可以使用索引*/ SELECT * FROM TABLE WHERE `name` LIKE '%sallen%';
五、常常與其餘表進行鏈接的表,在鏈接字段上應該創建索引
六、頻繁進行數據操做的表,不要創建太多的索引,由於 增刪改 都會對索引作更新,這樣會加劇mysql的負擔