亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

MySQL 統(tǒng)計(jì)信息以及執(zhí)行計(jì)劃預(yù)估方式初探

瀏覽:7日期:2023-10-16 13:17:13

數(shù)據(jù)庫(kù)中的統(tǒng)計(jì)信息在不同(精確)程度上描述了表中數(shù)據(jù)的分布情況,執(zhí)行計(jì)劃通過(guò)統(tǒng)計(jì)信息獲取符合查詢條件的數(shù)據(jù)大小(行數(shù)),來(lái)指導(dǎo)執(zhí)行計(jì)劃的生成。

在以O(shè)racle和SQLServer為代表的商業(yè)數(shù)據(jù)庫(kù),和以開(kāi)源的PostgreSQL為代表的數(shù)據(jù)庫(kù)中,直方圖是統(tǒng)計(jì)信息的一個(gè)重要組成部分。

在生成執(zhí)行計(jì)劃的時(shí)候,通過(guò)統(tǒng)計(jì)信息以及統(tǒng)計(jì)信息的直方圖來(lái)預(yù)估符合條件的數(shù)據(jù)行數(shù),從而影響執(zhí)行計(jì)劃的生成。

統(tǒng)計(jì)信息對(duì)執(zhí)行計(jì)劃的影響,具體體現(xiàn)在:索引的查找與掃描,多表連接時(shí)表之間的驅(qū)動(dòng)順序,表之間的JOIN方式,以及對(duì)sql查詢語(yǔ)句的資源分配等等。

但是在MySQL數(shù)據(jù)庫(kù)中,執(zhí)行計(jì)劃的方式相對(duì)簡(jiǎn)單,表之間的JOIN只有LOOPJOIN一種方式,且沒(méi)有并行執(zhí)行計(jì)劃等,也就說(shuō)通過(guò)預(yù)估結(jié)果集的行數(shù)對(duì)執(zhí)行計(jì)劃的影響有限。

但是對(duì)于某些情況,依舊需要預(yù)估的方式來(lái)指導(dǎo)執(zhí)行計(jì)劃的生成,

比如常見(jiàn)的多表連接時(shí)驅(qū)動(dòng)順序,多數(shù)情況下是小表驅(qū)動(dòng)大表(不完全一定)的方式來(lái)實(shí)現(xiàn)查詢的,因此MySQL中一樣需要預(yù)估來(lái)指導(dǎo)執(zhí)行計(jì)劃的生成。

不過(guò)MySQL中的統(tǒng)計(jì)信息相對(duì)來(lái)說(shuō)簡(jiǎn)單很多,只有一個(gè)cardinality信息來(lái)預(yù)估索引的選擇性(show index from table),

索引統(tǒng)計(jì)信息不包含直方圖的信息,非索引列也不會(huì)生成直方圖,也就是無(wú)法通過(guò)直方圖來(lái)預(yù)估查詢數(shù)據(jù)的大小,mysql是通過(guò)其他方式來(lái)實(shí)現(xiàn)預(yù)估的。

對(duì)于有直方圖的數(shù)據(jù)來(lái)說(shuō),直方圖為預(yù)估提供了重要的依據(jù),對(duì)于沒(méi)有直方圖的MySQL,執(zhí)行計(jì)劃是如何預(yù)估的?預(yù)估的準(zhǔn)確性有如何?

筆者在研究這個(gè)問(wèn)題的時(shí)候,一開(kāi)始也遇到不少疑惑的地方,還是看了博客園大神的問(wèn)題才得以釋惑,后面會(huì)給出鏈接。

首先通過(guò)例子,通過(guò)一個(gè)非常簡(jiǎn)單的查詢來(lái)觀察一個(gè)有意思的現(xiàn)象。

新建測(cè)試表,測(cè)試表如下:

create table test_statistics( id int auto_increment primary key, col2 varchar(200), col3 varchar(200), create_date datetime, index idx_create_date(create_date))ENGINE=InnoDB;

存儲(chǔ)過(guò)程通過(guò)循環(huán)插入數(shù)據(jù),調(diào)用存儲(chǔ)過(guò)程生成100W行數(shù)據(jù)(100W行的數(shù)據(jù),在實(shí)際應(yīng)用中已經(jīng)是一個(gè)非常小的數(shù)據(jù)量了),create_date字段上生成一個(gè)范圍之內(nèi)的隨機(jī)時(shí)間。

CREATE DEFINER=`root`@`%` PROCEDURE `p_insert_test_data`( IN `loop_count` INT)BEGIN declare i int; while (loop_count>0) do insert into test_statistics(col2,col3,create_date) values (uuid(),uuid(), DATE_ADD(sysdate(), INTERVAL -rand()*2400 hour));set loop_count = loop_count -1; end while;END

寫(xiě)入測(cè)試數(shù)據(jù)完成之后,進(jìn)行如下兩個(gè)查詢做測(cè)試。

簡(jiǎn)單地使用select count(1)的來(lái)做測(cè)試

首先看第一個(gè)查詢:查詢的時(shí)間范圍是: where create_date>’2017-11-01 12:00:00′ and create_date<’2017-11-01 16:00:00′

可以發(fā)現(xiàn):explain預(yù)估的行數(shù),與實(shí)際行數(shù)完全一致。

MySQL 統(tǒng)計(jì)信息以及執(zhí)行計(jì)劃預(yù)估方式初探

繼續(xù)第二個(gè)查詢,擴(kuò)大查詢的時(shí)間范圍,查詢的時(shí)間范圍是:where create_date>’2017-11-01 12:00:00′ and create_date<’2017-11-03 16:00:00′

可以發(fā)現(xiàn),此時(shí)的explain執(zhí)行計(jì)劃的預(yù)估,與實(shí)際行數(shù)出現(xiàn)了嚴(yán)重的偏差

MySQL 統(tǒng)計(jì)信息以及執(zhí)行計(jì)劃預(yù)估方式初探

為什么第一個(gè)查詢做到了精確的預(yù)估,而第二個(gè)查詢的預(yù)估出現(xiàn)嚴(yán)重的偏差?

這一點(diǎn)要從預(yù)估的計(jì)算方式入手來(lái)說(shuō)。

首先,第一個(gè)查詢和第二個(gè)查詢,唯一的不同是,第二個(gè)查詢的時(shí)間范圍放寬了,為什么時(shí)間放寬之后,執(zhí)行計(jì)劃的預(yù)估的準(zhǔn)確性就大大下降?

既然是“預(yù)估”,就一定是存在誤差,只不過(guò)是誤差大與小的問(wèn)題,誤差的大下與具體的預(yù)估的方式有關(guān)。

任何預(yù)估的實(shí)現(xiàn),都是以一種在不同程度上“以偏概全”的方式進(jìn)行的,比如SQL Server是以對(duì)相關(guān)數(shù)據(jù)page的通過(guò)某種百分比來(lái)取樣,然后存儲(chǔ)在直方圖中做預(yù)估依據(jù)的。

當(dāng)然,這種“以偏概全”的預(yù)估方式,是在性能與精確度之間權(quán)衡折中的結(jié)果.

在考慮收集統(tǒng)計(jì)信息對(duì)性能和資源影響的前提下,預(yù)估策略各種方式或者代價(jià)盡可能減少對(duì)預(yù)估產(chǎn)生誤差的因素,關(guān)于直方圖的生成這里不細(xì)說(shuō)。

對(duì)于沒(méi)有直方圖的MySQL,它是是在執(zhí)行的時(shí)候,通過(guò)掃描符合查詢條件的部分?jǐn)?shù)據(jù)頁(yè)后做預(yù)估統(tǒng)計(jì)的.

MySQL是在查詢的時(shí)候,直接對(duì)查詢條件范圍內(nèi)的數(shù)據(jù)頁(yè),取一定比例樣本做統(tǒng)計(jì)之后預(yù)估的,但是這里取樣的數(shù)據(jù)頁(yè)面有一定的限制,不會(huì)無(wú)限制取樣做統(tǒng)計(jì)預(yù)估。

如果符合條件的數(shù)據(jù)頁(yè)超出了預(yù)定的范圍,則會(huì)取部分頁(yè)進(jìn)行預(yù)估,而不是全部頁(yè)(為什么不是全部樣做統(tǒng)計(jì)預(yù)估,原因就不用說(shuō)了吧)。

比如下圖中,不管是聚集索引還是二級(jí)索引(非聚集索引),理論上說(shuō)都是一顆平衡樹(shù),暫不探究其細(xì)節(jié)。

假如符合條件的數(shù)據(jù)是一個(gè)范圍,位于兩個(gè)矩形框之間。矩形框分別是范圍的左右節(jié)點(diǎn),中間可以想象成多個(gè)葉子節(jié)點(diǎn)

參考zhanlijun大神的文章 ,

上述參考鏈接中得知,MySQL在5.5之后的預(yù)估原理如下:

其預(yù)估掃描的數(shù)據(jù)頁(yè)分別是前后兩個(gè)數(shù)據(jù)頁(yè),以及從左邊開(kāi)始連續(xù)8個(gè)數(shù)據(jù)頁(yè),得到平均每個(gè)page的行數(shù),根據(jù)總的page個(gè)數(shù)預(yù)估出這個(gè)范圍的數(shù)據(jù)行數(shù)。

具體說(shuō),也就是取左右兩個(gè)葉子節(jié)點(diǎn),以及從左葉子節(jié)點(diǎn)開(kāi)始連續(xù)8個(gè)頁(yè)的數(shù)據(jù)做統(tǒng)計(jì),中間可能有多個(gè)數(shù)據(jù)頁(yè),但也會(huì)被忽略,這就是上面提到的“以偏概全”的方式。

這里面就存在一個(gè)最明顯的問(wèn)題,也就是符合條件的數(shù)據(jù)頁(yè)面與預(yù)估時(shí)候采集的頁(yè)面的大小關(guān)系。

如果符合條件的數(shù)據(jù)頁(yè)的分布少于10個(gè),當(dāng)然在預(yù)估的時(shí)候,會(huì)全部掃描這些page,當(dāng)然預(yù)估是完全精確的,這也是第一個(gè)查詢執(zhí)行計(jì)劃預(yù)估的實(shí)際行數(shù)完全不一致的原因。

如果符合條件的數(shù)據(jù)頁(yè)的分布大于10個(gè),當(dāng)然在預(yù)估的時(shí)候,會(huì)部分掃描這些page,預(yù)估的誤差情況就此產(chǎn)生,這也是第二個(gè)查詢執(zhí)行計(jì)劃預(yù)估的實(shí)際行數(shù)差異較大的原因。

MySQL 統(tǒng)計(jì)信息以及執(zhí)行計(jì)劃預(yù)估方式初探

當(dāng)然MySQL的每個(gè)版本可能都有所改進(jìn)或者差異,筆者并沒(méi)有從源碼中找到具體的算法,當(dāng)前測(cè)試的是5.7.20版本。

但目前仍不清楚,

1,在create_date字段上,時(shí)間是按照DATE_ADD(sysdate(), INTERVAL -rand()*2400 hour)生成的,從整體分布看,基本按照時(shí)間均勻分布的.

理論上根據(jù)這種方式推到,得到的預(yù)估結(jié)果偏差應(yīng)該不會(huì)很大,但尚不清楚為什么預(yù)估與實(shí)際存在如此大的差異。

2,嘗試找到預(yù)估值從精確到產(chǎn)生差異的臨界點(diǎn),通過(guò)查詢實(shí)際行數(shù),根據(jù)key_len的值以及B樹(shù)索引的存儲(chǔ)原理(二級(jí)索引葉子節(jié)點(diǎn)存儲(chǔ)的二級(jí)索引的key值+聚集索引的key值).

理論上計(jì)算出來(lái)當(dāng)前查詢一個(gè)大概的取樣的page個(gè)數(shù),發(fā)現(xiàn)這個(gè)值預(yù)報(bào)理論上的10個(gè)page差異較大,可能是推到方式有問(wèn)題,或者是MySQL預(yù)估本身有一些不知道的細(xì)節(jié)問(wèn)題。

3,沒(méi)有詳細(xì)翻MySQL的源碼,尚未找到具體的實(shí)現(xiàn)細(xì)節(jié)。

對(duì)于有直方圖的數(shù)據(jù)庫(kù)來(lái)說(shuō),直方圖的信息也不是沒(méi)有代價(jià),或者是萬(wàn)能的,直方圖也有直方圖的局限性,這里暫不表述。

對(duì)于尚沒(méi)有直方圖的MySQL數(shù)據(jù)庫(kù)來(lái)說(shuō),其預(yù)估原理是每次查詢的時(shí)候進(jìn)行對(duì)相關(guān)的數(shù)據(jù)頁(yè)面進(jìn)行采樣預(yù)估的,而不是從直方圖中獲取到預(yù)估信息的,這是一個(gè)很消耗性能的操作。

詳情參考: http://www.orczhou.com/index.php/2013/04/how-mysql-choose-index-in-a-join/

這可能會(huì)導(dǎo)致MySQL不適合做較大數(shù)據(jù)量或者較為復(fù)雜的JOIN操作,當(dāng)然這也取決于具體的業(yè)務(wù)設(shè)計(jì)方案以及對(duì)數(shù)據(jù)的依賴程度,或者主觀上的查詢提示操作。

說(shuō)這句話是冒著被MySQL的大神以及粉絲們怒噴的風(fēng)險(xiǎn)的。

關(guān)于MySQL的預(yù)估的知識(shí)點(diǎn),搜索到的文章并不是很多,也拘泥于個(gè)人的認(rèn)識(shí)有限,也希望對(duì)這方面有關(guān)注的大神多多指點(diǎn)。

據(jù)說(shuō)MySQL在8.0之后的版本中會(huì)加入直方圖信息,以及其他JOIN方式(除了LOOP JOIN),這可能對(duì)性能上有比較大的幫助。

參考鏈接 https://www.cnblogs.com/LBSer/p/3333881.html http://www.orczhou.com/index.php/2013/04/how-mysql-choose-index-in-a-join/

來(lái)自:http://www.importnew.com/28075.html

標(biāo)簽: MySQL 數(shù)據(jù)庫(kù)
相關(guān)文章:
主站蜘蛛池模板: 成人亚洲视频在线观看 | 日韩大片免费在线观看 | 欧美日韩一区二区三区高清不卡 | 在线观看免费国产视频 | 国产综合91 | 精品无人区乱码一区二区三区手机 | 成 人色 网 站999 | www一级毛片| 国产在线观看黄色 | 久草手机在线观看视频 | 妖精视频在线观看网站 | 一本色道久久综合狠狠躁篇 | 国产91在线|亚洲 | 青青视频国产在线播放 | 国产真实偷乱视频在线观看 | 无码中文字幕日韩专区 | 国产丶欧美丶日韩丶不卡影视 | 在线观看黄色影视 | 九九99九九在线精品视频 | 国产色婷婷精品综合在线 | 国产免费自拍视频 | 国产在线精品一区二区 | 久久综合中文字幕一区二区三区 | 国产 在线 | 日韩 | 婷婷欧美 | 久久999精品| 欧美黄色一级 | 中日韩视频在线看免费观看 | 欧美一级视频免费观看 | 黄色日韩| 女人天堂网在线观看2019 | 免费中文字幕一级毛片 | 一级做a爰片 | 91精品综合国产在线观看 | julia中文字幕久久亚洲 | 欧美视频一区二区三区在线观看 | 日韩高清一区 | 毛片一级黄色 | 在线日韩欧美一区二区三区 | 麻豆视频传媒入口 | 99爱在线精品视频免费观看9 |