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

      歡迎訪問 生活随笔!

      生活随笔

      當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

      数据库

      SQL中基于代价的优化

      發(fā)布時(shí)間:2023/12/20 数据库 42 豆豆
      生活随笔 收集整理的這篇文章主要介紹了 SQL中基于代价的优化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

      還記得筆者在上篇文章無意中挖的一個(gè)坑么?如若不知,強(qiáng)烈建議看官先行閱讀前面兩文-《SparkSQL Join原理》和《Join中竟然也有謂詞下推?》
      第一篇文章主要分析了大數(shù)據(jù)領(lǐng)域Join的三種基礎(chǔ)算法以及各自的適用場景,第二篇文章在第一篇的基礎(chǔ)上進(jìn)一步深入,討論了Join基礎(chǔ)算法的一種優(yōu)化方案 – Runtime Filter,文章最后還引申地聊了聊謂詞下推技術(shù)。同時(shí),在第二篇文章開頭,筆者引出了兩個(gè)問題,SQL執(zhí)行引擎如何知曉參與Join的兩波數(shù)據(jù)集大小?衡量兩波數(shù)據(jù)集大小的是物理大小還是紀(jì)錄多少抑或兩者都有?這關(guān)系到SQL解析器如何正確選擇Join算法的問題。好了,這些就是這篇文章要為大家?guī)淼淖h題-基于代價(jià)優(yōu)化(Cost-Based Optimization,簡稱CBO)。

      CBO基本原理

      提到CBO,就不得不提起一位’老熟人’ – 基于規(guī)則優(yōu)化(Rule-Based Optimization,簡稱RBO)。RBO是一種經(jīng)驗(yàn)式、啟發(fā)式的優(yōu)化思路,優(yōu)化規(guī)則都已經(jīng)預(yù)先定義好,只需要將SQL往這些規(guī)則上套就可以(對(duì)RBO還不了解的童鞋,可以參考筆者的另一篇文章 – 《從0到1認(rèn)識(shí)Catalyst》)。說白了,RBO就像是一個(gè)經(jīng)驗(yàn)豐富的老司機(jī),基本套路全都知道。
      然而世界上有一種東西叫做 – 不按套路來,與其說它不按套路來,倒不如說它本身并沒有什么套路
      。最典型的莫過于復(fù)雜Join算子優(yōu)化,對(duì)于這些Join來說,通常有兩個(gè)選擇題要做:
      1、Join應(yīng)該選擇哪種算法策略來執(zhí)行?BroadcastJoin or ShuffleHashJoin or SortMergeJoin?不同的執(zhí)行策略對(duì)系統(tǒng)的資源要求不同,執(zhí)行效率也有天壤之別,同一個(gè)SQL,選擇到合適的策略執(zhí)行可能只需要幾秒鐘,而如果沒有選擇到合適的執(zhí)行策略就可能會(huì)導(dǎo)致系統(tǒng)OOM。
      2、對(duì)于雪花模型或者星型模型來講,多表Join應(yīng)該選擇什么樣的順序執(zhí)行?不同的Join順序意味著不同的執(zhí)行效率,比如A join B join C,A、B表都很大,C表很小,那A join B很顯然需要大量的系統(tǒng)資源來運(yùn)算,執(zhí)行時(shí)間必然不會(huì)短。而如果使用A join C join B的執(zhí)行順序,因?yàn)镃表很小,所以A join C會(huì)很快得到結(jié)果,而且結(jié)果集會(huì)很小,再使用小的結(jié)果集 join B,性能顯而易見會(huì)好于前一種方案。
      大家想想,這有什么固定的優(yōu)化規(guī)則么?并沒有。說白了,你需要知道更多關(guān)于表的基礎(chǔ)信息(表大小、表記錄總條數(shù)等),再通過一定規(guī)則代價(jià)評(píng)估才能從中選擇一條最優(yōu)的執(zhí)行計(jì)劃。CBO意為基于代價(jià)優(yōu)化策略,就是從多個(gè)可能的語法樹中選擇一條代價(jià)最小的語法樹來執(zhí)行,換個(gè)說法,CBO的核心在于評(píng)估出一條給定語法樹的實(shí)際代價(jià)。比如下面這顆SQL語法樹:

      要評(píng)估給定整棵樹的代價(jià),分而治之只需要評(píng)估每個(gè)節(jié)點(diǎn)執(zhí)行的代價(jià),最后將所有節(jié)點(diǎn)代價(jià)累加即可。而要評(píng)估單個(gè)節(jié)點(diǎn)執(zhí)行實(shí)際代價(jià),又需要知道兩點(diǎn),其一是這種算子的代價(jià)規(guī)則,每種算子的代價(jià)計(jì)算規(guī)則必然都不同,比如Merge-Sort Join、Shuffle Hash Join、GroupBy都有自己的一套代價(jià)計(jì)算算法。其二是參與操作的數(shù)據(jù)集基本信息(大小、總記錄條數(shù)),比如實(shí)際參與Merge-Sort Join的兩表大小,作為節(jié)點(diǎn)實(shí)際執(zhí)行代價(jià)的一個(gè)重要因素,當(dāng)然非常重要。試想,同樣是Table Scan操作,大表和小表的執(zhí)行代價(jià)必然不同。
      為給定算子的代價(jià)進(jìn)行評(píng)估說到底也是一種算法,算法都是死的,暫且不表,下文詳述。而參與的數(shù)據(jù)集基本信息卻是活的,為什么如此說,因?yàn)檫@些數(shù)據(jù)集都是原始表經(jīng)過過濾、聚合之后的中間結(jié)果,沒有規(guī)則直接告訴你這個(gè)中間結(jié)果有多少數(shù)據(jù)!那中間結(jié)果的基本信息如何評(píng)估呢?推導(dǎo)!對(duì),原始表基本信息我們是可以知道的,如果能夠一層一層向上推導(dǎo),是不是就有可能知道所求中間結(jié)果信息!
      這里又將任意節(jié)點(diǎn)中間結(jié)果信息評(píng)估拆分為兩個(gè)子問題:首先評(píng)估葉子節(jié)點(diǎn)(原始表)的基本信息,其次一層一層往上推導(dǎo)。評(píng)估原始表基本信息想想總是有辦法的,粗暴點(diǎn)就全表掃描,獲取記錄條數(shù)、最大值、最小值,總之是可以做到的。那基本信息如何一層一層往上推導(dǎo)呢?規(guī)則!比如原始表經(jīng)過 id = 12這個(gè)Filter過濾之后的數(shù)據(jù)集信息(數(shù)據(jù)集大小等)就可以經(jīng)過一定的規(guī)則推導(dǎo)出來,不同算子有不同的規(guī)則,下文詳述!
      好吧,上文花費(fèi)了大量時(shí)間將一個(gè)完整的CBO解剖的零零碎碎,變成了一堆規(guī)則加原始表的掃描。相信大家都有點(diǎn)懵懵的。莫慌,我們?cè)賮砝硪槐?#xff1a;
      1. 基于代價(jià)優(yōu)化(CBO)原理是計(jì)算所有執(zhí)行路徑的代價(jià),并挑選代價(jià)最小的執(zhí)行路徑。問題轉(zhuǎn)化為:如何計(jì)算一條給定執(zhí)行路徑的代價(jià)
      2. 計(jì)算給定路徑的執(zhí)行代價(jià),只需要計(jì)算這條路徑上每個(gè)節(jié)點(diǎn)的執(zhí)行代價(jià),最后相加即可。問題轉(zhuǎn)化為:如何計(jì)算其中任意一個(gè)節(jié)點(diǎn)的執(zhí)行代價(jià)
      3. 計(jì)算任意節(jié)點(diǎn)的執(zhí)行代價(jià),只需要知道當(dāng)前節(jié)點(diǎn)算子的代價(jià)計(jì)算規(guī)則以及參與計(jì)算的數(shù)據(jù)集(中間結(jié)果)基本信息(數(shù)據(jù)量大小、數(shù)據(jù)條數(shù)等)。問題轉(zhuǎn)化為:如何計(jì)算中間結(jié)果的基本信息以及定義算子代價(jià)計(jì)算規(guī)則
      4. 算子代價(jià)計(jì)算規(guī)則是一種死的規(guī)則,可定義。而任意中間結(jié)果基本信息需要通過原始表基本信息順著語法樹一層一層往上推導(dǎo)得出。問題轉(zhuǎn)化為:如何計(jì)算原始表基本信息以及定義推導(dǎo)規(guī)則

      很顯然,上述過程是思維過程,真正工程實(shí)踐是反著由下往上一步一步執(zhí)行,最終得到代價(jià)最小的執(zhí)行路徑。現(xiàn)在再把它從一個(gè)個(gè)零件組裝起來:
      1. 首先采集原始表基本信息
      2. 再定義每種算子的基數(shù)評(píng)估規(guī)則,即一個(gè)數(shù)據(jù)集經(jīng)過此算子執(zhí)行之后基本信息變化規(guī)則。這兩步完成之后就可以推導(dǎo)出整個(gè)執(zhí)行計(jì)劃樹上所有中間結(jié)果集的數(shù)據(jù)基本信息
      3. 定義每種算子的執(zhí)行代價(jià),結(jié)合中間結(jié)果集的基本信息,此時(shí)可以得出任意節(jié)點(diǎn)的執(zhí)行代價(jià)
      4. 將給定執(zhí)行路徑上所有算子的代價(jià)累加得到整棵語法樹的代價(jià)
      5. 計(jì)算出所有可能語法樹代價(jià),并選出一條代價(jià)最小的

      CBO基本實(shí)現(xiàn)思路

      上文從理論層面分析了CBO的實(shí)現(xiàn)思路,將完整的CBO功能拆分為了多個(gè)子功能,接下來聊聊對(duì)每一個(gè)子功能的實(shí)現(xiàn)。

      第一步:采集參原始表基本信息

      這個(gè)操作是CBO最基礎(chǔ)的一項(xiàng)工作,采集的主要信息包括表級(jí)別指標(biāo)和列級(jí)別指標(biāo),如下所示,estimatedSize和rowCount為表級(jí)別信息,basicStats和Histograms為列級(jí)別信息,后者粒度更細(xì),對(duì)優(yōu)化更加重要。

      • estimatedSize: 每個(gè)LogicalPlan節(jié)點(diǎn)輸出數(shù)據(jù)大小(解壓)
      • rowCount: 每個(gè)LogicalPlan節(jié)點(diǎn)輸出數(shù)據(jù)總條數(shù)
      • basicStats: 基本列信息,包括列類型、Max、Min、number of nulls, number of distinct values, max column length, average column length等
      • Histograms: Histograms of columns, i.e., equi-width histogram (for numeric and string types) and equi-height histogram (only for numeric types).

      這里有兩個(gè)問題值得思考:
      1、為什么要采集這些信息?每個(gè)對(duì)象在優(yōu)化過程中起到什么作用?
      2、實(shí)際工程一般是如何實(shí)現(xiàn)這些數(shù)據(jù)采集的?
      為什么要采集這些信息?很顯然,estimatedSize和rowCount這兩個(gè)值是算子代價(jià)評(píng)估的直觀體現(xiàn),這兩個(gè)值越大,給定算子執(zhí)行代價(jià)必然越大,所以這兩個(gè)值后續(xù)會(huì)用來評(píng)估實(shí)際算子的執(zhí)行代價(jià)。那basicStats和Histograms這倆用來干啥呢,要不忘初心,之所以采集原始表的這些信息,是為了順著執(zhí)行語法樹往上一層一層推導(dǎo)出所有中間結(jié)果的基本信息,這倆就是來干這個(gè)的,至于怎么實(shí)現(xiàn)的,下一小節(jié)會(huì)舉個(gè)例子解釋。
      實(shí)際工程如何實(shí)現(xiàn)這些數(shù)據(jù)采集?一般有兩種比較可行的方案:打開所有表掃描一遍,這樣最簡單,而且統(tǒng)計(jì)信息準(zhǔn)確,缺點(diǎn)是對(duì)于大表來說代價(jià)比較大;針對(duì)一些大表,掃描一遍代價(jià)太大,可以采用采樣(sample)的方式統(tǒng)計(jì)計(jì)算。
      支持CBO的系統(tǒng)都有命令對(duì)原始數(shù)據(jù)信息進(jìn)行統(tǒng)計(jì),比如Hive的Analyze命令、Impala的Compute命令、Greenplum的Analyze命令等,但是需要注意這些命令并不是隨時(shí)都應(yīng)該執(zhí)行的,首先在表數(shù)據(jù)沒有大變動(dòng)的情況下沒必要執(zhí)行,其次在系統(tǒng)查詢高發(fā)期也不應(yīng)該執(zhí)行。這里有個(gè)最佳實(shí)踐:盡可能在業(yè)務(wù)低峰期對(duì)表數(shù)據(jù)有較大變動(dòng)的表單獨(dú)執(zhí)行統(tǒng)計(jì)命令,這句話有三個(gè)重點(diǎn),不知道你看出來沒有?

      第二步:定義核心算子的基數(shù)推導(dǎo)規(guī)則

      規(guī)則推導(dǎo)意思是說在當(dāng)前子節(jié)點(diǎn)統(tǒng)計(jì)信息的基礎(chǔ)上,計(jì)算父節(jié)點(diǎn)相關(guān)統(tǒng)計(jì)信息的一套推導(dǎo)規(guī)則。對(duì)于不同算子,推導(dǎo)規(guī)則必然不一樣,比如fliter、group by、limit等等的評(píng)估推導(dǎo)是不同的。這里以filter為例進(jìn)行講解。先來看看這樣一個(gè)SQL:select * from A , C where A.id = C.c_id and C.c_id > N ,經(jīng)過RBO之后的語法樹如下圖所示:
      問題定義為:假如現(xiàn)在已經(jīng)知道表C的基本統(tǒng)計(jì)信息(estimatedSize、rowCount、basicStats以及histograms),如何推導(dǎo)出經(jīng)過C.c_id > N過濾后中間結(jié)果的基本統(tǒng)計(jì)信息。我們來看看:
      1、假設(shè)已知C列的最小值c_id.Min、最大值c_id.Max以及總行數(shù)c_id.Distinct,同時(shí)假設(shè)數(shù)據(jù)分布均勻,如下圖所示:

      2、現(xiàn)在分別有三種情況需要說明,其一是N小于c_id.Min,其二是N大于c_id.Max,其三是N介于c_id.Min和c_id.Max之間。前兩種場景是第三種場景的特殊情況,這里簡單的針對(duì)第三種場景說明。如下圖所示:

      在C.c_id > N過濾條件下,c_id.Min會(huì)增大到N,c_id.Max保持不變。而過濾后總行數(shù)c_id.distinct(after filter) = (c_id.Max – N) / (c_id.Max – c_id.Min) * c_id.distinct(before filter)
      簡單吧,但是注意哈,上面計(jì)算是在假設(shè)數(shù)據(jù)分布均勻的前提下完成的,而實(shí)際場景中數(shù)據(jù)分布很顯然不可能均衡。數(shù)據(jù)分布通常成概率分布,histograms在這里就要登場了,說白了它就是一個(gè)柱狀分布圖,如下圖:

      柱狀圖橫坐標(biāo)表示列值大小分布,縱坐標(biāo)表示頻率。假設(shè)N在如圖所示位置,那過濾后總行數(shù)c_id.distinct(after filter) = height(>N) / height(All) * c_id.distinct(before filter)
      當(dāng)然,上述所有計(jì)算都只是示意性計(jì)算,真實(shí)算法會(huì)復(fù)雜很多。另外,如果大家對(duì)group by 、limit等謂詞的評(píng)估規(guī)則比較感興趣的話,可以閱讀SparkSQL CBO設(shè)計(jì)文檔,在此不再贅述。至此,通過各種評(píng)估規(guī)則以及原始表統(tǒng)計(jì)信息就可以計(jì)算出語法樹中所有中間節(jié)點(diǎn)的基本統(tǒng)計(jì)信息了,這是萬里長征的第二步,也是至關(guān)重要的一步。接下來繼續(xù)往前走,看看如何計(jì)算每種核心算子的實(shí)際代價(jià)。

      第三步:核心算子實(shí)際代價(jià)計(jì)算

      打文章一開始就開口閉口代價(jià)代價(jià)的,可到底什么是代價(jià),怎么定義代價(jià)?這么說吧,每個(gè)系統(tǒng)對(duì)代價(jià)的定義并不非常一致,有的因?yàn)閷?shí)現(xiàn)的原因設(shè)置的比較簡單,有的會(huì)比較復(fù)雜。這一節(jié)主要來簡單聊聊每個(gè)節(jié)點(diǎn)的執(zhí)行代價(jià),上文說了,一條執(zhí)行路徑的總代價(jià)就是這條路徑上所有節(jié)點(diǎn)的代價(jià)累加之和。
      通常來講,節(jié)點(diǎn)實(shí)際執(zhí)行代價(jià)主要從兩個(gè)維度來定義:CPU Cost以及IO Cost。為后續(xù)講解方便起見,需要先行定義一些基本參數(shù):

      • Hr:從HDFS上讀取1byte數(shù)據(jù)所需代價(jià)
      • Hw:往HDFS上寫入1byte數(shù)據(jù)所需代價(jià)
      • Tr:數(shù)據(jù)總條數(shù)(the number of tuples in the relation )
      • Tsz:數(shù)據(jù)平均大小(Average size of the tuple in the relation )
      • CPUc:兩值比較所需CPU資源代價(jià)(CPU cost for a comparison in nano seconds )
      • NEt:1byte數(shù)據(jù)通過網(wǎng)絡(luò)在集群節(jié)點(diǎn)間傳輸花費(fèi)代價(jià)(the average cost of transferring 1 byte
        over network in the Hadoop cluster from any node to any node )
      • ……
      • 上文說過,每種算子的實(shí)際執(zhí)行代價(jià)計(jì)算方式都不同,在此不可能列舉所有算子,就挑兩個(gè)比較簡單、容易理解的來分析,第一個(gè)是Table
        Scan算子,第二個(gè)是Hash Join算子。

      Table Scan算子
      Scan算子一般位于語法樹的葉子結(jié)點(diǎn),直觀上來講這類算子只有IO Cost,CPU Cost為0。Table Scan Cost = IO Cost = Tr * Tsz * Hr,很簡單,Tr * Tsz表示需要scan的數(shù)據(jù)總大小,再乘以Hr就是所需代價(jià)。OK,很直觀,很簡單。
      Hash Join算子
      以Broadcast Hash Join為例(如果看官對(duì)Broadcast Hash Join工作原理還不了解,可戳這里),假設(shè)大表分布在n個(gè)節(jié)點(diǎn)上,每個(gè)節(jié)點(diǎn)的數(shù)據(jù)條數(shù)\平均大小分別為Tr(R1)\Tsz(R1),Tr(R2)\Tsz(R2), … Tr(Rn)\Tsz(Rn),小表數(shù)據(jù)條數(shù)為Tr(Rsmall)\Tsz(Rsmall),那么CPU代價(jià)和IO代價(jià)分別為:
      CPU Cost = 小表構(gòu)建Hash Table代價(jià) + 大表探測代價(jià) = Tr(Rsmall) * CPUc + (Tr(R1) + Tr(R2) + … + Tr(Rn)) * N * CPUc,此處假設(shè)HashTable構(gòu)建所需CPU資源遠(yuǎn)遠(yuǎn)高于兩值簡單比較代價(jià),為N * CPUc
      IO Cost = 小表scan代價(jià) + 小表廣播代價(jià) + 大表scan代價(jià) = Tr(Rsmall) * Tsz(Rsmall) * Hr + n * Tr(Rsmall) * Tsz(Rsmall) * NEt + (Tr(R1)* Tsz(R1) + … + Tr(Rn) * Tsz(Rn)) * Hr
      很顯然,Hash Join算子相比Table Scan算子來講稍稍復(fù)雜了一點(diǎn),但是無論哪種算子,代價(jià)計(jì)算都和參與的數(shù)據(jù)總條數(shù)、數(shù)據(jù)平均大小等因素直接相關(guān),這也就是為什么在之前兩個(gè)步驟中要不懈余力地計(jì)算中間結(jié)果相關(guān)詳細(xì)的真正原因。可謂是步步為營、環(huán)環(huán)相扣。這下好了,任意節(jié)點(diǎn)的實(shí)際代價(jià)都能評(píng)估出來,那么給定任意執(zhí)行路徑的代價(jià)必然也就很簡單嘍。

      第四步:選擇最優(yōu)執(zhí)行路徑(代價(jià)最小執(zhí)行路徑)

      這個(gè)思路很容易理解的,經(jīng)過上述三步的努力,可以很容易地計(jì)算出任意一條給定路徑的代價(jià)。那么你只需要找出所有可行的執(zhí)行路徑,一個(gè)一個(gè)計(jì)算,就必然能找到一個(gè)代價(jià)最小的,也就是最優(yōu)的執(zhí)行路徑。
      這條路看起來確實(shí)很簡單,但實(shí)際做起來卻并不那么容易,為什么?所有可行的執(zhí)行路徑實(shí)在太多,所有路徑都計(jì)算一遍,黃花菜都涼了。那么有什么好的解決方案么?當(dāng)然,其實(shí)看到這個(gè)標(biāo)題-選擇代價(jià)最小執(zhí)行路徑,就應(yīng)該很容易想到-動(dòng)態(tài)規(guī)劃,如果你沒有想到,那只能說明你沒有讀過《數(shù)學(xué)之美》、沒刷過LeetCode、沒玩過ACM,ACM、LeetCode如果覺得太枯燥,那就去看看《數(shù)學(xué)之美》,它會(huì)告訴你從當(dāng)前這個(gè)你所在的地方開車去北京,如何使用動(dòng)態(tài)規(guī)劃選擇一條最短的路線。在此不再贅述。
      至此,筆者粗線條地介紹了當(dāng)前主流SQL引擎是如何將CBO這么一個(gè)看似高深的技術(shù)一步一步落地的。接下來,筆者將會(huì)借用Hive、Impala這兩大SQL引擎開啟CBO之后的優(yōu)化效果讓大家對(duì)CBO有一個(gè)更直觀的理解。

      Hive – CBO優(yōu)化效果

      Hive本身沒有去從頭實(shí)現(xiàn)一個(gè)SQL優(yōu)化器,而是借助于Apache Calcite ,Calcite是一個(gè)開源的、基于CBO的企業(yè)級(jí)SQL查詢優(yōu)化框架,目前包括Hive、Phoniex、Kylin以及Flink等項(xiàng)目都使用了Calcite作為其執(zhí)行優(yōu)化器,這也很好理解,執(zhí)行優(yōu)化器本來就可以抽象成一個(gè)系統(tǒng)模塊,并沒有必要花費(fèi)大量時(shí)間去重復(fù)造輪子。
      hortonworks曾經(jīng)對(duì)Hive的CBO特性做了相關(guān)的測試,測試結(jié)果認(rèn)為CBO至少對(duì)查詢有三個(gè)重要的影響:Join ordering optimization、Bushy join support以及Join simplification,本文只簡單介紹一下Join ordering optimization,有興趣的同學(xué)可以繼續(xù)閱讀這篇文章來更多地了解其他兩個(gè)重要影響。(下面數(shù)據(jù)以及示意圖也來自于該篇文章,特此注明)
      hortonworks對(duì)TPCDS的部分Query進(jìn)行了研究,發(fā)現(xiàn)對(duì)于大部分星型\雪花模型,都存在多Join問題,這些Join順序如果組織不好,性能就會(huì)很差,如果組織得當(dāng),性能就會(huì)很好。比如Query Q3:

      select dt.d_year,item.i_brand_id brand_id,item.i_brand brand,sum(ss_ext_sales_price) sum_agg from date_dim dt,store_sales,item where dt.d_date_sk = store_sales.ss_sold_date_sk and store_sales.ss_item_sk = item.i_item_sk and item.i_manufact_id =436 and dt.d_moy =12 groupby dt.d_year , item.i_brand , item.i_brand_id order by dt.d_year , sum_agg desc , brand_id limit 10

      上述Query涉及到3張表,一張事實(shí)表store_sales(數(shù)據(jù)量大)和兩張維度表(數(shù)據(jù)量小),三表之間的關(guān)系如下圖所示:

      這里就涉及上文提到的Join順序問題,從原始表來看,date_dim有73049條記錄,而item有462000條記錄。很顯然,如果沒有其他暗示的話,Join順序必然是store_sales join date_dim join item。但是,where條件中還帶有兩個(gè)條件,CBO會(huì)根據(jù)過濾條件對(duì)過濾后的數(shù)據(jù)進(jìn)行評(píng)估,結(jié)果如下:

      TableTableCardinality after filterSelectivity
      date_dim73,04962008.5%
      item462,0004840.1%

      根據(jù)上表所示,過濾后的數(shù)據(jù)量item明顯比date_dim小的多,劇情反轉(zhuǎn)的有點(diǎn)快。于是乎,經(jīng)過CBO之后Join順序就變成了store_sales join item join date_time,為了進(jìn)一步確認(rèn),可以在開啟CBO前后分別記錄該SQL的執(zhí)行計(jì)劃,如下圖所示:
      左圖是未開啟CBO特性時(shí)Q3的執(zhí)行計(jì)劃,store_sales先與date_dim進(jìn)行join,join后的中間結(jié)果數(shù)據(jù)集有140億條。而再看右圖,store_sales先于item進(jìn)行join,中間結(jié)果只有8200w條。很顯然,后者執(zhí)行效率會(huì)更高,實(shí)踐出真知,來看看兩者的實(shí)際執(zhí)行時(shí)間:

      TableQuery Response Time(seconds)Intermediate RowsCPU(seconds)
      Q3 CBO OFF25513,987,506,88451,967
      Q3 CBO ON14286,217,65335,036

      上圖很明顯的看出Q3在CBO的優(yōu)化下性能將近提升了1倍,與此同時(shí),CPU資源使用率也降低了一半左右。不得不說,TPCDS中有很多相似的Query,有興趣的同學(xué)可以深入進(jìn)一步深入了解。

      Impala – CBO優(yōu)化效果

      和Hive優(yōu)化的原理相同,也是針對(duì)復(fù)雜join的執(zhí)行順序、Join的執(zhí)行策略選擇優(yōu)化等方面進(jìn)行的優(yōu)化,本人使用TPC-DS對(duì)Impala在開啟CBO特性前后的部分Query進(jìn)行了性能測試,測試結(jié)果如下圖所示:

      參考:
      http://hbasefly.com/2017/05/04/bigdata%ef%bc%8dcbo/

      創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

      總結(jié)

      以上是生活随笔為你收集整理的SQL中基于代价的优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

      如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

      主站蜘蛛池模板: 天堂视频在线观看免费 | 老司机av导航 | 亚洲电影一区二区三区 | 在线观看av的网站 | 欧美日本一道 | 日韩精品视频在线观看免费 | 操极品女神 | 国产精品丝袜视频无码一区69 | 国产麻豆精品一区二区 | 波多野吉衣一区二区 | 色综合天天网 | 欧美一级免费视频 | free性中国hd国语露脸 | 日韩成人免费电影 | 一区二区不卡在线观看 | 国产精品秘| 国模精品视频一区二区 | 好吊日精品视频 | 99爱免费 | 精品国产91久久久久久久妲己 | 国产精品91一区二区 | 国产在线xxxx | 亚洲国产福利视频 | 亚洲区小说区 | 啪啪网站免费 | 久久久久成人精品无码中文字幕 | 亚洲13p | 91福利网址 | 国产福利免费观看 | 日韩精品电影一区 | 久久精品午夜 | 字幕网在线观看 | 永久免费无码av网站在线观看 | 在线观看日韩一区 | 自拍第一区 | 极品白嫩丰满少妇无套 | 色悠悠在线视频 | 亚洲女人天堂成人av在线 | 国产精品久久久久久久久绿色 | 粉嫩av一区二区三区四区五区 | 18视频在线观看网站 | 男人爱看的网站 | 欧美性欧美zzzzzzzzz | 五月婷婷综合久久 | 天天操天天干天天摸 | 蜜桃av鲁一鲁一鲁一鲁俄罗斯的 | 亚欧洲精品在线视频 | 国产午夜福利一区二区 | 91蜜臀精品国产自偷在线 | 99热免费观看| 一本在线 | 精品久久免费观看 | 午夜鲁鲁 | 国产欧美日韩精品区一区二污污污 | 三上悠亚在线观看一区二区 | 日本不卡一区视频 | 日韩熟妇一区二区三区 | 国产一级片免费视频 | 天天操狠狠操 | 色呦呦中文字幕 | 国产免费久久 | 99久久久久无码国产精品 | 嫩嫩av| 九色影院 | av在线资源 | 成年人免费av | 欧美黄色性视频 | 国产在线视频二区 | 欧美人性生活视频 | 逼特逼视频在线观看 | 免费看国产片在线观看 | 激情五月婷婷在线 | 春色网站| 国产69精品久久 | 精品国产一区三区 | 亚洲经典一区二区 | 18欧美性xxxx极品hd | 国产精品一区网站 | 国产精品123区 | 国产精品高潮呻吟 | 欧美黄色短片 | 国产高清99 | 欧美私人情侣网站 | 国产高清www | 久久精品aⅴ无码中文字字幕重口 | 日韩欧美一区视频 | 粉嫩精品久久99综合一区 | 你懂的欧美 | 成人黄色激情小说 | 午夜精品久久久久久久久 | 男男gay同性三级 | 91一级视频 | 亚洲另类av | 欧美操女人 | 免费的黄色一级片 | 精品一区二区中文字幕 | xx99小雪| 亚洲欧美一区二区激情 | 欧美日韩在线观看视频 |