日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL性能优化[实践篇]-复合索引实例

發布時間:2023/12/20 数据库 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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性能优化[实践篇]-复合索引实例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。