MySQL索引選擇及規則整理
索引選擇性
索引選擇性就是結果個數與總個數的比值。
用sql語句表示為:
SELECT COUNT(*) FROM table_name WHERE column_name/SELECT COUNT(*) FROM table_name
一般來說(例如書 “SQL Tuning“),如果選擇性超過 20% 那麼全表掃描比使用索引效能更優。
但MySQL是沒有計算索引的選擇性的,只是預測邏輯IO操作的數量,因此對於MySQL索引要慎重選擇。
舉個栗子,tinyint型別的列,用以儲存性別,就算用上“保密”和“變性”2項,選擇性也最小也才25%,因此也就沒有設定索引的必要了。
索引規則
以下是整理出來的規則,以供參考:(由於很多實際專案都是查詢操作佔了絕大部分,因此不必太過呆板)
- 選擇維度高的列
- 選擇 where,on,group by,order by 中出現的列
- 選擇較小的資料列,這樣的索引檔案更小,同時可裝載更多的索引鍵
- 為較長的字串使用字首索引
- 組合索引能減低索引檔案的大小,使用速度也優於多個單列索引
- 切勿濫用索引,因為除了磁碟空間的開銷外,每次增刪改都需要重新建立索引
- 索引不會包含有NULL值的列(若組合索引包含NULL值的列則整個組合索引無效)
另外,使用索引應當儘量避免 “OR” 、“否定查詢” 、“模糊查詢”、“NOT IN”、“<>” 等操作!
注意:字首索引和組合索引是建立索引的一種技巧,並非索引型別。
組合索引
假設test表中有a,b,c三個列。
ALTER TABLE test ADD INDEX abc(a,b,c);
相當於分別建立了
a,b,c
a,b
a
這樣的3組索引,也是“最左字首”這個規則的結果。
舉個使用該組合索引的栗子:
SELECT * FROM test WHERE a="1" AND b="2" SELECT * FROM test WHERE a="1"
以下則用不到索引:
SELECT * FROM test WHERE b="1" AND c="2" SELECT * FROM test WHERE c="1"
因此組合索引有一定優勢,但在使用上需謹慎。
字首索引
MySQL 字首索引能有效減小索引檔案的大小,提高索引的速度。但是字首索引也有它的壞處:MySQL 不能在 ORDER BY 或 GROUP BY 中使用字首索引,也不能把它們用作覆蓋索引(Covering Index)。
語法如下:
ALTER TABLE table_name ADD KEY column_name(prefix_length);
建立字首索引的關鍵在於"prefix_length"這個引數,並且字首索引的選擇性上也有一點特殊。
字首索引的選擇性公式為:SELECT COUNT(DISTINCT column_name)/COUNT(*) FROM table_name
繼續舉栗子!
現在有個user表,列 family_name varchar(50) 儲存的是英文姓氏(我也想用中文姓名來舉例,但是不大適合,看下去就明白了。。。)
要取得設定字首索引最理想的"prefix_length",我們首先要取得整列的選擇性,如下:
SELECT COUNT(DISTINCT family_name)/COUNT(*) FROM user;
假設這裡得到值是0.188。
然後我們繼續去看看該列前1個字元的選擇性又是多少
SELECT COUNT(DISTINCT LEFT(family_name,1))/COUNT(*) FROM user;
假設這裡得到的結果是0.532,和整列的選擇性出入太大,不可取,繼續:
SELECT COUNT(DISTINCT LEFT(family_name,2))/COUNT(*) FROM user;
SELECT COUNT(DISTINCT LEFT(family_name,3))/COUNT(*) FROM user;
...
假設直接到“prefix_length”為5時,得到的值為0.189,非常接近!
而取6時得到的值為0.18891,這個選擇性和5並沒有太大的偏差。
再結合減少索引檔案大小的這個思路
“prefix_length”值設定為5才是此處設定字首索引的最優方案!
選擇性講完,還得再講清楚這個字首索引該怎麼用!
書接上面的栗子~
正確的用法如下:
SELECT * FROM user WHERE family_name LIKE "lee%";
SELECT * FROM user WHERE family_name LIKE "david%";
以下則用不上該索引:
SELECT * FROM user WHERE family_name LIKE "_ee%";
SELECT * FROM user WHERE family_name LIKE "%en%";
SELECT * FROM user WHERE family_name LIKE "%ar%";
注意:SQL的模式預設是忽略大小寫的!
另外,“_”代表一個字元,“%”代表任意多個字元!
相關文章
- 索引選擇度問題最佳化整理索引
- 表資料量影響MySQL索引選擇MySql索引
- MySQL innodb如何選擇一個聚簇索引MySql索引
- CSS 選擇器優先順序規則CSS
- 如何選擇普通索引和唯一索引《死磕MySQL系列 五》索引MySql
- mysql索引為啥要選擇B+樹 (下)MySql索引
- mysql索引為啥要選擇B+樹 (上)MySql索引
- MySQL資料庫索引選擇使用B+樹MySql資料庫索引
- MySQL索引建立原則MySql索引
- 核範數與規則項引數選擇
- MySQL索引(二):建索引的原則MySql索引
- 面試 (MySQL 索引為啥要選擇 B+ 樹)面試MySql索引
- MySQL學習之影響優化器選擇索引因素MySql優化索引
- 對線面試官:Mysql組合索引的生效規則面試MySql索引
- mysql 索引設計原則MySql索引
- [Mysql]索引選型MySql索引
- MySQL 選錯索引MySql索引
- Elasticsearch 中為什麼選擇倒排索引而不選擇 B 樹索引Elasticsearch索引
- 唯一索引和普通索引的選擇索引
- MySQL進階【五】—— MySQL查詢優化器是如何選擇索引的MySql優化索引
- Debug: 樣式規則、元素選擇器 錯誤嵌用
- MySQL 索引的設計原則MySql索引
- 資料庫索引選擇策略資料庫索引
- pandas索引和選擇資料索引
- MYSQL索引及高效能索引策略MySql索引
- 關於mysql字符集及排序規則設定MySql排序
- 五分鐘,讓你明白MySQL是怎麼選擇索引《死磕MySQL系列 六》MySql索引
- 深入探討MySQL索引的設計原則及最佳化策略MySql索引
- Mysql研磨之設計索引原則MySql索引
- MySQL 選錯索引的原因?MySql索引
- 正則化與模型選擇模型
- 「 MySQL高階篇 」MySQL索引原理,設計原則MySql索引
- 普通索引和唯一索引,應該怎麼選擇?索引
- 理解Mysql索引原理及特性MySql索引
- MySQL的索引原理及使用MySql索引
- mysql索引原理及優化MySql索引優化
- 【MySQL】批次修改排序規則MySql排序
- Oracle 選擇題知識點整理Oracle