索引使用建議:前端
a,常常檢索的列mysql
b,常常用於錶鏈接的列sql
c,常常排序/分組的列session
索引不使用建議:數據結構
a,基數很低的列函數
b,常常用於錶鏈接的列優化
c,常常排序/分組的列spa
innodb主鍵特色:設計
a,索引定義時,若不顯示包含主鍵,會隱式加入主鍵值;server
b,索引定義時,若顯示包含主鍵,會加入主鍵值;
c,在5.6.9後,優化器已經能自動識別索引末尾的主鍵值(index extensions),在這以前則須要顯式加上主鍵列才能夠被識別;
d,修改主鍵必然從新拷貝整張表
主鍵的選擇建議:
a,對業務透明無心義,免收業務變化的影響;
b,主鍵要不多修改和刪除;(刪除還好,影響不大,innodb小範圍作數據頁合併)
c,主鍵最好是自增的;
d,不要具備動態屬性,例如最後修改時間戳;(若是常常變化會致使彙集索引的值發生變化,相應的致使btree索引值旋轉、分裂、位移)
innodb彙集索引選擇順序原則:
a,顯示聲明的主鍵;
b,第一個不包含null值的惟一索引列;
c,內置的rowid(自增邏輯值,6byte且不可引用)
innodb彙集索引不建議選用頻繁更新、隨機寫入(離散IO)
惟一索引(unique key)
a,不容許具備索引值相同的行,從而禁止重複的索引或鍵值;
b,在惟一約束上,和主鍵同樣(以myisam引擎爲表明);
c,和主鍵區別:1,惟一索引容許有空值(null) 2,一個表只能有一個主鍵,但能夠有多個惟一索引 3,innodb表中主鍵必須是彙集索引,但彙集索引可能不是主鍵(未定義主鍵、也沒有非null的惟一索引時會選擇rowid) 4,惟一索引約束能夠臨時禁用,但主鍵不行(set session UNIQUE_CHECKS = 0;),即使禁用惟一性約束,也沒法插入相同值。那麼,關閉還有什麼意義?大量導入數據時就不須要每行都檢測惟一性是否衝突,最後一次性檢測有沒有重複,效率更高些。若是不想告警可使用 on duplicate key update(先insert,若是失敗就update);
聯合索引(combined indexes,multiple-column indexes)
a,多列組成,因此也叫多列索引
b,適合where條件中的多列組合
c,有時候,還能夠用於避免回表(覆蓋索引)
d,以往有列引用順序,如今已經沒有這個限制了
e,mysql還不支持多列不一樣排序規則(order by a.b.c,desc;這個不ok)
f,聯合索引建議:1,where條件中,常常同時出現的列放在聯合索引中。2,聯合索引包含的列數越多,會增長死鎖的機率。
覆蓋索引:
a,經過索引數據結構,便可直接返回數據,不須要回表
b,執行計劃中,顯示關鍵字using index
前綴索引(prefix indexes):
部分索引的緣由:1,char/varchar太長所有作索引的話,效率太差,存在浪費。2,blob/text類型不能整列做爲索引列,所以須要前綴索引。
部分索引的選擇建議:1,統計平均值。2,遵循2/8原則(覆蓋80%數據就OK)
外鍵約束(foreign key constraints)
a,確保存儲在外鍵表中的數據一致性,完整性;
b,外鍵前提:本表列須與外鍵類型相同(外鍵須是外表主鍵);
c,外鍵選擇原則:1,爲關聯字段建立外鍵。2,全部的鍵都必須惟一。3,避免使用複合鍵;4,外鍵老是關聯惟一的鍵字段。
mysql支持全文索引,但不建議使用IO,內存,CPU都是瓶頸。
可使用pt-duplicate-key-checker檢查冗餘索引,pt-index-usage檢查低利用率索引,並提供刪除建議。
索引如何提升sql效率?
a,提升數據檢索效率
b,提升聚合函數效率,sum()、avg()、count()
c,有時能夠避免回表
d,減小多表關聯掃描行數
e,惟1、外鍵索引還能夠做爲輔助約束
f,列定義DEFAULT NULL時,NULL值也會有索引,存放在索引樹的最左端,最前端部分,所以儘可能不要定義爲NULL。
何時索引不可用?
a,經過索引掃描的記錄數超過30%,會變成全表掃描
b,聯合索引中,第一個索引列使用範圍查詢(這時用到部分索引)
c,聯合索引中,第一個查詢條件不是最左索引列
d,模糊查詢條件列最左通配符%開始
e,HEAP表使用HASH索引時,使用範圍檢索或者ORDER BY
f,多表關聯時,排序字段不屬於驅動表,沒法利用索引完成排序(這點很重要,詳見下圖案例,強制更改驅動表可能影響結果集)
g,兩個獨立索引,其中一個用於檢索,一個用於排序(只能用到一個)
ICP(index condition pushdown)是mysql5.6的新特性,其機制會讓索引的其餘部分也參與過濾,減小引擎層和server層數據傳輸和回表請求,一般狀況下可大幅度提高查詢效率。
覆蓋索引:
假設有這樣的索引:key 'idx1'('id','user','passwd')
覆蓋索引都被用到:
a,select id,user,passwd from t1 where id=?
b,select id,user,passwd from t1 where id=? and user=?
c,select id,user,passwd from t1 where id=? and user=? and passwd=?
覆蓋索引部分被用到:
a,select id,user,passwd from t1 where passwd=? and id=?
b,select id,user from t1 where id =? order by user;
c,select id,user from t1 where id=? order by passwd;
explain之key_len
a,正常狀況等於索引列字節長度
b,字符串類型須要同時考慮字符集因素
c,若容許null,再+1
d,變長類型(如varchar)再+2
key_len只計算利用索引完成數據過濾的索引長度
不包括用於group by\order by的索引長度
即:若是order by也使用了索引,不會將其計算在key_len以內
例如:聯合索引(c1,c2,c3),where c1 = ? and c2 = ? order by c3.這時,key_len只會顯示c1+c2的長度
#eq_range_index_dive_limit 默認值是200,in值只要不超過200都是等值查詢,超過200執行代價會有變化。
索引設計建議:
a,一個索引裏包含的個數最好不要超過5個
b,一個表的索引數,不要太多,通常不要超過5個
c,聯合索引中把過濾性高(基數大)的列放在前面