MySQL性能优化[实践篇]-复合索引实例
上篇文章最后提了個問題
假設某個表有一個復合索引(c1,c2,c3,c4),問以下查詢中只能使用該復合索引的c1,c2,c3部分的有那些
1. where c1=x and c2=x and c4>x and c3=x
2. where c1=x and c2=x and c4=x order by c3
3. where c1=x and c4=x group by c3,c2
4. where c1=? and c5=? order by c2,c3
5. where c1=? and c2=? and c5=? order by c2,c3
建表測試
測試表中有五個列(c1,c2,c3,c4,c5),均為char(1)類型且不為空。字符集為utf8(索引長度以字節數計算)
創建復合索引
插入幾條測試數據
這里插幾條數據,主要是為了防止空表對SQL優化器的影響
where c1=x and c2=x and c4>x and c3=x
用到了索引的所有部分,其中c1,c2,c3精確匹配,c4范圍查詢:
這里key_len=12,因為每個utf8字符占3個字節(BMP平面字符)。
雖然utf8對A、B、C這幾個英文字符的編碼方式與ASCII是兼容的(也就是一個字節),但char(1)為了保證能有足夠的空間存儲完整的utf8字符(比如中文),它會盡量申請一個最大的單字符空間,不然將來修改字符比較麻煩。也就是說MySQL會將原本utf8變長編碼使用定長存儲。
而utf8四字節以上的字符都屬于補充平面,幾乎不可能用到,所以MySQL就取了3個字節一個字符,這三字節utf8在mysql中叫做utf8mb3,mysql也支持4字節的utf8編碼——utf8mb4。MySQL中utf8指的就是utf8mb3。另外我們建表時對每個字段都指定了not null的約束,如果使用默認的default null會多出一個字節。
關于utf-8編碼原理可以參考《從ASCII、ISO-8859、GB2312、GBK到Unicode的UCS-2、UCS-4、UTF-8、UTF-16、UTF-32》
關于MySQL對Unicode編碼的支持可以參考《Unicode Support》
Using index condition
出現Using index condition意味著沒有達到索引覆蓋。
查詢語句通過索引過濾出幾條記錄,但是查詢的內容超出索引范圍,需要讀取完整的數據行(這個過程也被叫做ICP,Index Condition Pushdown)。
出現ICP主要是因為我們用了select *。我們把SQL稍微改動一下,讓它能達到索引覆蓋
where c1=x and c2=x and c4=x order by c3
用到了索引的c1,c2,c3列,其中c1、c2列用于查詢,c3用于排序。由于c3列沒有精確匹配,導致c4列無法用到索引。
type: ref
ref指的是從表中讀取匹配索引值的所有行。type=ref說明使用了索引的左前綴,或者完整地使用了索列但是索引不是primary key或unique key。
換句話說type=ref表明,查詢語句不能通過索引查找到單獨一行數據。
相反type: eq_ref就是使用了primary key或unique key的查詢,這種查詢能從表中唯一一條記錄。
where c1=x and c4=x group by c3,c2
group by子句執行時會先排序,再分組。這條語句由于group by的順序為c3,c2與索引順序不匹配,所以沒用到索引。
我們把group by的順序調換一下就能然c2和c3列能用上索引進行排序分組。
where c1=? and c5=? order by c2,c3
因為group by本質上也會執行order by操作,所以這條語句原理上和上面的差不多。
where c1=? and c2=? and c5=? order by c2,c3
這條查詢和上條略有不同c1列和c2列已經使用索引精確匹配了,而order by再對c2進行排序已經沒有意義了,因為過濾后的數據c2都是相等的,所以實際上只有c3列才用到排序。
這個時候的修改order by中c2、c3列的順序沒有任何關系,因為c2列已經精確匹配了。
1. where c1=x and c2=x and c4>x and c3=x
? 用到(c1,c2,c3,c4)列進行數據查找
2. where c1=x and c2=x and c4=x order by c3
? 用到(c1,c3)列進行數據查找,c3列索引排序
3. where c1=x and c4=x group by c3,c2
? 只是用了(c1)列進行數據查找
4. where c1=? and c5=? order by c2,c3
? 使用(c1)列進行數據查找,c2,c3列索引排序
5. where c1=? and c2=? and c5=? order by c2,c3
? 使用(c1,c2)列進行數據查找,c3列索引排序
這個問題原出自一個論壇,這里重新測試并對結果稍作整理
參考:
- https://dev.mysql.com/doc/refman/5.7/en/explain-output.html
總結
以上是生活随笔為你收集整理的MySQL性能优化[实践篇]-复合索引实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 陈潇冰php,webpack4.x入门到
- 下一篇: oci mysql_Oracle常用的O