掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
周五下班后,或是DBA同學(xué)已下班沒(méi)找到,或是考慮到我在公司維護(hù)著數(shù)據(jù)庫(kù)中間件,對(duì)數(shù)據(jù)庫(kù)這類問(wèn)題會(huì)有一些經(jīng)驗(yàn),邢老師找來(lái)說(shuō)是討論一個(gè)奇怪的sql執(zhí)行計(jì)劃問(wèn)題,我本是稍有自信,但經(jīng)過(guò)簡(jiǎn)單上下文同步和一番操作演示討論后,我也覺(jué)得這個(gè)情況挺奇怪,讓人有點(diǎn)懵。

創(chuàng)新互聯(lián)公司專注于桑日企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè)公司,購(gòu)物商城網(wǎng)站建設(shè)。桑日網(wǎng)站建設(shè)公司,為桑日等地區(qū)提供建站服務(wù)。全流程定制制作,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)
原始案例完整同步的性價(jià)比不高,我簡(jiǎn)單描述一下,能跟讀者認(rèn)知對(duì)齊就好;情況大概是這樣:一個(gè)表里除了有主鍵,還涉及到另外3個(gè)索引,A索引、B索引、A+B組合索引,使用不同的索引explain中顯示的預(yù)估行數(shù)rows的結(jié)果是不同的,情況如下,其中第3條很讓人疑惑:
|
索引情況 |
查詢計(jì)劃 |
實(shí)際結(jié)果行數(shù) |
預(yù)估掃描行數(shù) |
|
存在A、B兩個(gè)字段的獨(dú)立索引 |
僅命中A索引檢索(where a= xxx) |
26 |
26 |
|
存在A、B兩個(gè)字段的獨(dú)立索引 |
僅命中B索引(where b=yyy) |
256 |
255 |
|
存在A、B兩個(gè)字段的獨(dú)立索引 |
命中A索引和B索引(where a= xxx and b = yyy) |
9 |
4 |
|
有A+B兩個(gè)字段的組合索引 |
命中A+B組合索引(where a= xxx and b = yyy) |
9 |
9 |
已經(jīng)好久沒(méi)專門研究數(shù)據(jù)庫(kù)底層的東西了,多年前曾對(duì)《SQL Server技術(shù)內(nèi)幕》系列叢書有潛心研讀,略有積累,這幾本書分別是:T-SQL程序設(shè)計(jì),T-SQL查詢 ,存儲(chǔ)引擎,查詢調(diào)整及優(yōu)化(如果用到SQL Server的話,這些書推薦去看看);雖然對(duì)SQL Server執(zhí)行計(jì)劃調(diào)優(yōu)這方面有一些認(rèn)知儲(chǔ)備,但當(dāng)天討論的畢竟是MySQL,張冠李戴并不是技術(shù)人的作風(fēng),原理及現(xiàn)象不敢太肯定。
這種索引情況MySQL 是以B+樹(shù)結(jié)構(gòu)來(lái)組織管理索引頁(yè)和數(shù)據(jù)頁(yè)
2.2 執(zhí)行計(jì)劃
執(zhí)行計(jì)劃是數(shù)據(jù)庫(kù)的查詢優(yōu)化器根據(jù)用戶輸入的SQL語(yǔ)句,以及其內(nèi)部的執(zhí)行策略和統(tǒng)計(jì)信息選擇出一個(gè)其認(rèn)為執(zhí)行效率最優(yōu)的計(jì)劃,然后使用這個(gè)計(jì)劃獲取數(shù)據(jù)。我們通常借助執(zhí)行計(jì)劃查看數(shù)據(jù)庫(kù)如何處理SQL語(yǔ)句,分析性能瓶頸。
在select前面加explain關(guān)鍵字,執(zhí)行后可看到下圖中的執(zhí)行計(jì)劃信息
下表是對(duì)執(zhí)行計(jì)劃信息各字段的簡(jiǎn)單介紹,本文的重點(diǎn)是其中的rows字段。
從官網(wǎng)可看到以下描述
Therows column indicates the number of rows MySQL believes it must examine to execute the query.For InnoDB tables, this number is an estimate, and may not always be exact.
漢化:rows 列表示MySQL認(rèn)為執(zhí)行查詢必須檢查的行數(shù)。對(duì)于InnoDB,這個(gè)數(shù)字是一個(gè)估計(jì),不一定準(zhǔn)確。
官網(wǎng)這話很精辟,但其內(nèi)部的一些關(guān)鍵設(shè)計(jì)卻并未提及。
如果是聚簇索引,那這個(gè)行數(shù)是 索引頁(yè)+數(shù)據(jù)頁(yè)中的記錄行數(shù)嘛?
如果是非聚簇索引,那這個(gè)行數(shù)是僅非聚簇索引頁(yè)中的索引記錄行數(shù)嘛?
如果查詢優(yōu)化器決定使用全表掃描的方式對(duì)某個(gè)表執(zhí)行查詢時(shí),執(zhí)行計(jì)劃的 rows 列就代表預(yù)計(jì)需要掃描的行數(shù)。
如果使用索引來(lái)執(zhí)行查詢時(shí),執(zhí)行計(jì)劃的 rows 列就代表預(yù)計(jì)掃描的索引記錄行數(shù)。
這有可能是個(gè)精確值,也可能是個(gè)估算值,計(jì)算方法有 index dive 和基于索引統(tǒng)計(jì)的估算。
1、2兩條跟A說(shuō)法相似,且未提到更多的細(xì)節(jié),但第3條信息就很重要了,給前邊的疑問(wèn)提供了一些線索,MySQL也是會(huì)基于統(tǒng)計(jì)信息來(lái)選擇執(zhí)行計(jì)劃的,統(tǒng)計(jì)信息是會(huì)有誤差的;只是 index dive 是什么呢?統(tǒng)計(jì)信息又是怎樣的實(shí)現(xiàn)機(jī)制呢?
獲取索引對(duì)應(yīng)的B+樹(shù)的 區(qū)間最左記錄和區(qū)間最右記錄,然后再計(jì)算這兩條記錄之間有多少記錄(記錄條數(shù)少的時(shí)候可以做到精確計(jì)算,多的時(shí)候只能估算)。MySQL把這種通過(guò)直接訪問(wèn)索引對(duì)應(yīng)的B+樹(shù)來(lái)計(jì)算某個(gè)范圍區(qū)間對(duì)應(yīng)的索引記錄條數(shù)的方式稱之為Index dive。
跟Index dive相關(guān)的有一個(gè)配置參數(shù) eq_range_index_dive_limit,作用大概是這樣:
從這個(gè)信息再次看出,采用Index div會(huì)較精準(zhǔn)的預(yù)估掃描行數(shù),但估算成本較高,適合小數(shù)據(jù)量。
索引統(tǒng)計(jì)估算成本較低,適合數(shù)據(jù)量大的情況。但使用索引統(tǒng)計(jì)的話,評(píng)估不準(zhǔn),甚至誤差很大,為什么誤差大以及誤差到底有多大,接下來(lái)再搜集相關(guān)資料來(lái)了解。
查詢優(yōu)化是在代價(jià)統(tǒng)計(jì)分析的基礎(chǔ)上進(jìn)行的,合理的代價(jià)模型和準(zhǔn)確的代價(jià)統(tǒng)計(jì)信息決定了查詢優(yōu)化的優(yōu)劣。My SQL的代價(jià)模型依賴的主要因素是IO和CPU,IO主要跟數(shù)據(jù)量和緩存相關(guān),CPU主要跟參與排序比較的記錄數(shù)相關(guān)。因此統(tǒng)計(jì)信息的指標(biāo)主要是數(shù)據(jù)量和記錄數(shù),如:
innodb的統(tǒng)計(jì)信息
以innodb_table_stats表為例,各個(gè)列的說(shuō)明:
|
列名 |
說(shuō)明 |
|
database_name |
數(shù)據(jù)庫(kù)名 |
|
table_name |
表名 |
|
last_update |
本條記錄最后更新時(shí)間 |
|
n_rows |
表中記錄的條數(shù) |
|
clustered_index_size |
表的聚簇索引占用的頁(yè)面數(shù)量 |
|
sum_of_other_index_sizes |
表的其他索引占用的頁(yè)面數(shù)量 |
顯而易見(jiàn),這其中的n_rows很關(guān)鍵,那他的值是怎么算的呢?
執(zhí)行計(jì)劃中的預(yù)估的行數(shù)依賴n_rows,InnoDB中n_rows的統(tǒng)計(jì)是這樣的:
由此可知n_rows值是否精確取決于統(tǒng)計(jì)時(shí)采樣的頁(yè)面數(shù)量,通過(guò)innodb_stats_persistent_sample_pages設(shè)置,設(shè)置的越大,統(tǒng)計(jì)出的相對(duì)越精確,但是耗時(shí)也會(huì)增加;設(shè)置得越小,統(tǒng)計(jì)出的值越不精確,但是統(tǒng)計(jì)耗時(shí)就少,要視實(shí)際情況而定。
MySQL中以下情況會(huì)觸發(fā)統(tǒng)計(jì)信息更新:
其第一種是發(fā)生變動(dòng)的記錄數(shù)量超過(guò)了表大小的10%,那么服務(wù)器會(huì)自動(dòng)觸發(fā)一次異步的統(tǒng)計(jì)數(shù)據(jù)的計(jì)算;其他方式是手動(dòng)觸發(fā)。
本篇主要是基于一次日常工作中的技術(shù)溝通,以執(zhí)行計(jì)劃中rows為主線,搜集資料梳理認(rèn)知;可知識(shí)是無(wú)限的,到現(xiàn)在也還未能探索出跟預(yù)期不一致的實(shí)際的計(jì)算過(guò)程,也只是達(dá)到對(duì)此知識(shí)點(diǎn)有個(gè)淺層的系統(tǒng)的認(rèn)知,幫助后續(xù)繼續(xù)分析探索其內(nèi)幕;同時(shí)也希望本次學(xué)習(xí)中的記錄能夠?qū)δ阌幸妗?/p>
本文轉(zhuǎn)載自微信公眾號(hào)「架構(gòu)染色」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系聯(lián)系【架構(gòu)染色】公眾號(hào)作者。
https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
https://blog.csdn.net/u022812849/article/details/120145037
https://www.cnblogs.com/ldws/p/12349502.html
https://baijiahao.baidu.com/s?id=1740652003821645078&wfr=spider&for=pc
https://mp.weixin.qq.com/s/-7qU1MPlBin4XdjhzTG-TQ
https://baijiahao.baidu.com/s?id=1740652003821645078&wfr=spider&for=pc

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流