SQL優(yōu)化之基于SQL特征的改寫(xiě)

前言

主要從事網(wǎng)頁(yè)設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、響應(yīng)式網(wǎng)站建設(shè)、程序開(kāi)發(fā)、微網(wǎng)站、小程序開(kāi)發(fā)等,憑借多年來(lái)在互聯(lián)網(wǎng)的打拼,我們?cè)诨ヂ?lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了豐富的網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作、網(wǎng)絡(luò)營(yíng)銷(xiāo)經(jīng)驗(yàn),集策劃、開(kāi)發(fā)、設(shè)計(jì)、營(yíng)銷(xiāo)、管理等多方位專(zhuān)業(yè)化運(yùn)作于一體,具備承接不同規(guī)模與類(lèi)型的建設(shè)項(xiàng)目的能力。



今天老K繼續(xù)與大家分享第九期。


周末老K宅在家觀戰(zhàn)了兩局精彩的“人狗”大戰(zhàn)。老K既算不上科技迷,也算不上圍棋迷,不過(guò)對(duì)此頗有感觸:阿爾法狗不過(guò)是通過(guò)左右互博的方式不斷學(xué)習(xí)圍棋,然而依賴(lài)其最優(yōu)的學(xué)習(xí)算法(學(xué)習(xí)方法)卻能再短短的數(shù)月之內(nèi)達(dá)到人類(lèi)圍棋水平的最頂端;而李世石在卻是依賴(lài)其已有的經(jīng)驗(yàn)結(jié)合人類(lèi)特有的靈感下出“神之一手”,人類(lèi)終究還是可以戰(zhàn)勝擁有超強(qiáng)計(jì)算能力的阿爾法狗。這些不禁讓老K想起了自己在工作過(guò)程中的最有藝術(shù)性的部分---“SQL tunning”,一方面要不斷學(xué)習(xí)積累運(yùn)用不同的優(yōu)化方法,同時(shí)在必要時(shí)多一分想象力和靈感,這樣面對(duì)不同的SQL問(wèn)題,我們才能下出自己的“神之一手”。


好了,今天老K與大家分享的案例是SQL調(diào)優(yōu)的案例,但老K更希望大家能從中體會(huì)到SQL tunning過(guò)程中的優(yōu)化方法和思維方式,真正做到它山之石,可以攻玉。同時(shí),大家如果覺(jué)得老K的方法還不錯(cuò),不妨輕輕的轉(zhuǎn)發(fā)一下,分享給身邊更多的ORACLE技術(shù)愛(ài)好者。

今天分析的問(wèn)題是客戶(hù)DBA給過(guò)來(lái)的一條SQL語(yǔ)句,已經(jīng)困擾其一段時(shí)間了,希望老K一起來(lái)分析解決。解決這個(gè)問(wèn)題對(duì)老K來(lái)說(shuō)并不是特別難,不過(guò)在這個(gè)問(wèn)題的分析過(guò)程中,老K給出了幾種優(yōu)化的方向,最終選擇了不論是對(duì)整個(gè)系統(tǒng)還是對(duì)該條SQL都可謂最佳的一種方式,最后在測(cè)試環(huán)境執(zhí)行效果非常不錯(cuò)。



Part 1

擺問(wèn)題、列信息


對(duì)于SQL tunning,老K上手最先關(guān)注的是SQL文本、執(zhí)行計(jì)劃和執(zhí)行統(tǒng)計(jì)信息,當(dāng)然也不要忘了關(guān)注一下系統(tǒng)/數(shù)據(jù)庫(kù)版本。


1.1 環(huán)境介紹


操作系統(tǒng) AIX 6.1

數(shù)據(jù)庫(kù) ORACLE 11.2.0.3 兩節(jié)點(diǎn)RAC


1.2 SQL文本

SQL優(yōu)化之基于SQL特征的改寫(xiě)

1.3 執(zhí)行計(jì)劃

SQL優(yōu)化之基于SQL特征的改寫(xiě)


1.4 執(zhí)行統(tǒng)計(jì)信息

SQL優(yōu)化之基于SQL特征的改寫(xiě)


信息都在這了,我們要關(guān)注些什么呢?老K的經(jīng)驗(yàn)是,先找特征,再根據(jù)不同的特征來(lái)進(jìn)一步提取自己需要的信息。


Part 2

找特征、補(bǔ)信息

2.1 SQL文本特征


 >> exists子句 (part1)和update set部分(part2)的sql代碼基本相同,如下圖;

>> part1部分中,標(biāo)量子查詢(xún)的結(jié)果作為set列的目標(biāo)值,說(shuō)明從業(yè)務(wù)邏輯上能保證該部查詢(xún)返回記錄數(shù)最多為1;

SQL優(yōu)化之基于SQL特征的改寫(xiě)

2.2 執(zhí)行計(jì)劃的特征

>> 該執(zhí)行計(jì)劃各過(guò)程均使用filter

>> 結(jié)合sql文本及predicate information可以看到,對(duì)目標(biāo)表TARGET_BIG_TABLE經(jīng)過(guò)濾條件POST_DATE=:V1后,返回記錄數(shù)預(yù)估為623K條。

SQL優(yōu)化之基于SQL特征的改寫(xiě)

2.3 補(bǔ)充信息收集之表統(tǒng)計(jì)信息


>> TARGET_BIG_TABLE大約2G大小,SOURCE_SMALL_TABLE大約3M 大??;

>> TARGET_BIG_TABLE表中記錄數(shù)約250W左右,統(tǒng)計(jì)信息估算POST_DATE過(guò)濾后返回623K條記錄,注意:這是預(yù)估值,實(shí)際值會(huì)隨著傳入的變量V1而變化。

>> SOURCE_SMALL_TABLE表中記錄數(shù)約12W左右,ad02_acct_no列的選擇度比較高;


2.4 補(bǔ)充信息收集之執(zhí)行計(jì)劃解讀


注:TARGET_BIG_TABLE簡(jiǎn)稱(chēng)為T(mén)表    SOURCE_SMALL_TABLE 簡(jiǎn)稱(chēng)為S表

另注:解讀關(guān)鍵----理解執(zhí)行計(jì)劃中的filter


>> 執(zhí)行計(jì)劃分開(kāi)成兩部分來(lái)看,其中ID2-7步表示對(duì)應(yīng)SQL文本的part2部分,ID8-12步對(duì)應(yīng)SQL文本的part1部分;


>> part2部分的過(guò)程:使用POST_DATE過(guò)濾T表,將過(guò)濾后的記錄迭代入EXISTS子查詢(xún)(T表的結(jié)果集此時(shí)作為變量傳入子查詢(xún)),在子查詢(xún)執(zhí)行的過(guò)程中,如果前面的關(guān)聯(lián)條件符合,再次迭代入第二層子查詢(xún)(select max()部分)進(jìn)行匹配;


>> part1部分的過(guò)程:針對(duì)ID2-7步過(guò)濾出的結(jié)果集,逐條update,而update的目標(biāo)值,同樣是通過(guò)類(lèi)似2-7步過(guò)程中的逐步迭代查詢(xún)而來(lái);


>> 在各步驟單表訪問(wèn)方式均為全表掃描;


>> 從執(zhí)行計(jì)劃中可以看到,在第3步對(duì)表T表進(jìn)行過(guò)濾之后結(jié)果集估算為623K(rows列),其后對(duì)S表過(guò)濾后均為1;


>> 由此可以估算執(zhí)行過(guò)程中表訪問(wèn)的情況應(yīng)為:(老K建議在本分享中記住下面的公式,暫且稱(chēng)之為 “ 訪問(wèn)公式 ” 吧)


過(guò)濾過(guò)程的表訪問(wèn)=(T表全掃+  623K 次 ×(S表全掃  +(0或者 1次)×(S表全掃)))

修改過(guò)程的表訪問(wèn)=(需要修改的記錄數(shù)  ×(S表全掃  + (0或者 1次)×(S表全掃)))

總的訪問(wèn)過(guò)程=過(guò)濾過(guò)程的表訪問(wèn)次數(shù) +修改過(guò)程的表訪問(wèn)

注意:此處的(0或者 1次)×(S表全掃)表示的是第二層子查詢(xún)的情況,如果在第一層子查詢(xún)過(guò)程中關(guān)聯(lián)條件就不符合,則不再需要迭代入第二層,即0次S表全掃,否則即是1次S表全掃;所以過(guò)濾過(guò)程對(duì)S表最少需要做623K次全掃,最多需要做1246K次全掃;修改過(guò)程同理。


2.5 執(zhí)行統(tǒng)計(jì)信息特征


>> SQL單次執(zhí)行平均邏輯讀為355,245,774(block數(shù))

>> SQL單次執(zhí)行平均時(shí)間約2000秒

>> SQL單次平均修改記錄數(shù)約為0條

SQL優(yōu)化之基于SQL特征的改寫(xiě)

Part 3

思考吧DBA


好了,信息收集完成了,進(jìn)入老K的既定思考軌道,其實(shí)對(duì)于任何一個(gè)SQL tunning的問(wèn)題,老K都會(huì)提出下面的三個(gè)問(wèn)題,這個(gè)也不用例外;


3.1 老K的例行思考


>> 這個(gè)執(zhí)行計(jì)劃是否為當(dāng)前SQL語(yǔ)句下最優(yōu)的執(zhí)行計(jì)劃?(選擇優(yōu)化目標(biāo))

>> 我們想要的執(zhí)行計(jì)劃是什么樣的?(確定優(yōu)化目標(biāo))

>> 我們?cè)趺磥?lái)讓SQL跑出我們想要的執(zhí)行計(jì)劃?(實(shí)現(xiàn)優(yōu)化目標(biāo))


如果可以,正在閱讀此文的你,也許也可以思考一下上面的三個(gè)問(wèn)題,或者回憶一下當(dāng)你面對(duì)SQL tunning的問(wèn)題時(shí)你有沒(méi)有思考過(guò)這三個(gè)問(wèn)題,亦或者你會(huì)思考/思考過(guò)什么呢。

綜合前期的分析思考片刻之后,老K鄭重地給出了自己的答案:


3.2 老K的答案----不是最優(yōu)的計(jì)劃


老K先查看過(guò)該SQL的歷史執(zhí)行計(jì)劃,只有這一個(gè),但這并不意味著著就是該SQL的最優(yōu)執(zhí)行計(jì)劃;


在執(zhí)行計(jì)劃解讀部分,老K給出了這個(gè)執(zhí)行計(jì)劃的“訪問(wèn)公式”,從公式中可以知道其實(shí)S表雖小,但其實(shí)際上是整個(gè)執(zhí)行計(jì)劃的關(guān)鍵,整個(gè)過(guò)程中最多可能需要對(duì)S表進(jìn)行1246K×2次訪問(wèn)呢,那我們可不可以提高對(duì)S表的訪問(wèn)效率呢?當(dāng)然可以,從執(zhí)行計(jì)劃中的估算可以知道對(duì)S表的訪問(wèn)大約返回1-2條記錄(這里老K還單獨(dú)驗(yàn)證過(guò)),說(shuō)明整體選擇度比較高,我們只有創(chuàng)建合適的索引,就可以就可以大大將提高S表的訪問(wèn)效率。


我們簡(jiǎn)單來(lái)估算一下使用索引的情況下的執(zhí)行效率是怎樣的。原來(lái)對(duì)S表全掃所需的邏輯讀數(shù)為3M(表大?。?192=375次,使用索引后預(yù)估對(duì)S表一次訪問(wèn)最多所需邏輯讀數(shù)為:(2次索引塊訪問(wèn) + 2次數(shù)據(jù)塊訪問(wèn))=4次;所以說(shuō),使用索引的邏輯讀約為使用全掃的的1%,估算創(chuàng)建索引后該語(yǔ)句單次執(zhí)行平均邏輯讀約在350w左右。


那么,新建索引,將S表的全掃都變?yōu)樗饕龗呙?,這就是老K想要的執(zhí)行計(jì)劃嗎?

顯然不是,這樣的執(zhí)行計(jì)劃只是原執(zhí)行計(jì)劃的一個(gè)升級(jí)版而已,其過(guò)程還是一個(gè)迭代的過(guò)程,這樣執(zhí)行的時(shí)間/消耗的時(shí)間基本都會(huì)隨著原計(jì)劃中第3步返回的數(shù)據(jù)量(還記得623K這個(gè)值嗎,就是它!它是可變的,可能隨著傳入的)變化而線性變化;所以這個(gè)執(zhí)行計(jì)劃雖然較原執(zhí)行計(jì)劃預(yù)計(jì)會(huì)有非常大的改善,但仍然不是老K想要的執(zhí)行計(jì)劃。


3.3 老K的答案----想要的計(jì)劃


SQL文本告訴我們,其實(shí)SQL做的就是使用exists方式將T表和S表進(jìn)行關(guān)聯(lián)更新,老K想要的執(zhí)行計(jì)劃應(yīng)該是使用NL或者h(yuǎn)ash join的方式來(lái)連接兩表,而不是使用filter迭代的方式,這樣就能保證SQL執(zhí)行過(guò)程中只需要對(duì)T表和S表進(jìn)行極少的一次或幾次掃描,從而降低SQL執(zhí)行的邏輯讀。


3.4 老K的答案----如何生成漂亮的執(zhí)行計(jì)劃


要回答這個(gè)問(wèn)題,我們首先要思考為什么SQL當(dāng)前沒(méi)有跑出我們想要的執(zhí)行計(jì)劃,是因?yàn)榻y(tǒng)計(jì)信息不準(zhǔn)?索引設(shè)計(jì)不合理?還是列類(lèi)型不匹配?

都不是!

我們?cè)俅位氐絊QL語(yǔ)句本身,來(lái)看看SQL語(yǔ)句的特別之處。

SQL優(yōu)化之基于SQL特征的改寫(xiě)

在這里,我們看到了問(wèn)題的關(guān)鍵,正是因?yàn)樽钔鈱拥腡表與兩層子查詢(xún)均有關(guān)聯(lián)關(guān)系,導(dǎo)致ORACLE無(wú)法自動(dòng)改寫(xiě)SQL,最終生成執(zhí)行計(jì)劃時(shí)無(wú)法使用T表與S表進(jìn)行JOIN,只能生成使用filter方式的執(zhí)行計(jì)劃。


所以,最終思考的結(jié)果已經(jīng)出來(lái):

>> 因?yàn)閮蓪幼硬樵?xún)的原因?qū)е翺RACLE無(wú)法使用JOIN的方式關(guān)聯(lián)T表和S表

>> 要想生成較好的執(zhí)行計(jì)劃必須改寫(xiě)語(yǔ)句

>> 改寫(xiě)后的語(yǔ)句不應(yīng)該存在類(lèi)似的最外層表涉及第二層子查詢(xún)的情況

其中最后一點(diǎn),指出了我們改寫(xiě)的關(guān)鍵點(diǎn)。


Part 4

改寫(xiě)吧DBA


依據(jù)老K的經(jīng)驗(yàn),SQL語(yǔ)句的改寫(xiě)通常要求改寫(xiě)者對(duì)SQL涉及業(yè)務(wù)非常了解,通過(guò)業(yè)務(wù)特征重構(gòu)出合理的SQL語(yǔ)句,才能更好的做到既不改變SQL的業(yè)務(wù)邏輯,又有效提高SQL性能;不過(guò)針對(duì)這個(gè)SQL,我們已經(jīng)知道了導(dǎo)致其執(zhí)行計(jì)劃不優(yōu)的根本原因,老K相信可以在不考慮業(yè)務(wù)特性的情況,利用數(shù)據(jù)庫(kù)的特性來(lái)進(jìn)行有效的改寫(xiě)。


4.1 改寫(xiě)的花絮


基于SQL特性中,part1和part2基本相同的特性,老K先隨性的對(duì)SQL做了如下改寫(xiě)(當(dāng)然沒(méi)有針對(duì)前面提到的改寫(xiě)關(guān)鍵點(diǎn));

SQL優(yōu)化之基于SQL特征的改寫(xiě)

這一改寫(xiě)方式的幾個(gè)關(guān)鍵點(diǎn):

>> 先把post_date字段的過(guò)濾條件直接提取出來(lái),與原邏輯一致

>> 基于part1和part2基本相同,使用了nvl函數(shù)代替了原來(lái)的exists子句

>> 如果select部分能查到記錄(類(lèi)似原來(lái)的exists子句成立),則用查詢(xún)出的結(jié)果更新chq_pay_name字段

>> 如果select部分不能查到記錄,則用原記錄自身進(jìn)行更新(set chq_pay_name=chq_pay_name),更新前后該記錄的數(shù)據(jù)不變


以上幾點(diǎn)保證了改寫(xiě)后的SQL與原SQL邏輯一致,不過(guò)有一點(diǎn)不一樣的非常值得注意,原SQL只修改極少的幾條記錄,新SQL卻修改了623K條記錄,只是其中絕大多數(shù)是冗余的修改。


我們?cè)倏锤膶?xiě)后的SQL執(zhí)行計(jì)劃:

SQL優(yōu)化之基于SQL特征的改寫(xiě)

與原SQL執(zhí)行計(jì)劃類(lèi)似,不過(guò)少了原執(zhí)行計(jì)劃的part1部分。

新的執(zhí)行計(jì)劃,老K又問(wèn)了自己一句:


4.2 這樣改寫(xiě)真的好嗎?


大家是否還記得原執(zhí)行計(jì)劃解析過(guò)程中老K給出的“訪問(wèn)公式”:

總的訪問(wèn)過(guò)程=過(guò)濾過(guò)程的表訪問(wèn)次數(shù) +修改過(guò)程的表訪問(wèn)

那么,在這個(gè)執(zhí)行計(jì)劃下,因?yàn)槿サ袅巳哂嗟囊徊糠?,公式就變成了?/p>

總的訪問(wèn)過(guò)程=過(guò)濾過(guò)程的表訪問(wèn)次數(shù)


實(shí)際上就可以理解為,SQL在修改數(shù)據(jù)的過(guò)程中可以重用過(guò)濾過(guò)程中生成的數(shù)據(jù);

不過(guò)針對(duì)這個(gè)語(yǔ)句,我們從執(zhí)行統(tǒng)計(jì)信息里知道,每次語(yǔ)句執(zhí)行最終修改的數(shù)據(jù)量都非常少,也就是說(shuō)這樣改寫(xiě)所減少的“修改過(guò)程的表訪問(wèn)”對(duì)整體執(zhí)行效率影響并不大。


這樣改寫(xiě)會(huì)帶來(lái)什么壞處嗎?

會(huì)!根本原因就在于上面提到的新SQL實(shí)際修改的記錄數(shù)是623K條:


>> 持有行鎖范圍變大,可能大量導(dǎo)致其他對(duì)該表進(jìn)行DML操作的會(huì)話(huà)被阻塞

>> 如果修改列上有索引,索引維護(hù)的時(shí)間將大大增加,導(dǎo)致新SQL執(zhí)行效率更低


綜上,針對(duì)這條SQL語(yǔ)句,這種改寫(xiě)方式并不合適。

不過(guò),如果原SQL在執(zhí)行過(guò)程中修改的數(shù)據(jù)量接近623K條,那么這種改寫(xiě)方式的收益就要高非常多,而其帶來(lái)的壞處也就不復(fù)存在了,這種改寫(xiě)方式只是不適合這種業(yè)務(wù)環(huán)境下(每次只修改極少幾條記錄),然而卻有一定的普遍性,所以老K也把這部分分享給大家,最重要的是解決問(wèn)題過(guò)程中的思路和方法。


4.3 繼續(xù)改寫(xiě)


前面我們已經(jīng)分析出改寫(xiě)的關(guān)鍵點(diǎn):改寫(xiě)后的語(yǔ)句不應(yīng)該存在類(lèi)似的最外層表涉及第二層子查詢(xún)的情況;下面我們就朝著這個(gè)目標(biāo)去改寫(xiě)我們的SQL語(yǔ)句。


改寫(xiě)前信息補(bǔ)充:

改寫(xiě)思路在老K腦中醞釀好后,老K又補(bǔ)查了T表的信息,確認(rèn)T表存在主鍵約束,主鍵列為ACCT_NO和JRNL_NO;


4.4 增加冗余

SQL優(yōu)化之基于SQL特征的改寫(xiě)

>> 在exists子句中增加一個(gè)冗余的T表,別名為d

>> 增加d表和a表的關(guān)聯(lián)關(guān)系,其中jrnl_no列和acct_no列組合為T(mén)表的主鍵,其他冗余列的關(guān)聯(lián)主要為下一步繼續(xù)的改寫(xiě)作鋪墊;

>> 整個(gè)SQL語(yǔ)句中沒(méi)有使用d表與其他表進(jìn)行關(guān)聯(lián);

>> 由于d表和a表使用的是主鍵進(jìn)行關(guān)聯(lián),所以能確保對(duì)a表的每條記錄,都能從d中找到且只能找到一條記錄符合語(yǔ)句中的關(guān)聯(lián)關(guān)系;


綜上,可以知道上述增加冗余完全不改變SQL的邏輯關(guān)系。


4.5 關(guān)鍵角色轉(zhuǎn)變:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

基于第一步冗余等價(jià)關(guān)系,將exists子句中的所有a與b、c的關(guān)聯(lián)關(guān)系替換為d與b、c的關(guān)聯(lián)關(guān)系。


4.6 減少冗余:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

因?yàn)橹麈Ia、d的主鍵列值相等,即可保證a、d的其他列值必然相等,所以a、d的關(guān)聯(lián)字段只需要保留主鍵字段即可(保留也是可以的,去掉顯得更簡(jiǎn)潔)


以上一步一步的改寫(xiě)保證了邏輯的一致性,同時(shí)實(shí)現(xiàn)了最外層的T表不再涉及第二層子查詢(xún)的關(guān)聯(lián),我們可以推斷執(zhí)行計(jì)劃應(yīng)該與老K預(yù)期的相差不遠(yuǎn)了:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

>> 執(zhí)行計(jì)劃中b、d、c表使用hash join進(jìn)行關(guān)聯(lián)

>> join完成后通過(guò)一系列SORT/FILTER后形成結(jié)果集VW_SQ_2,其中這里的filter部分為結(jié)果集內(nèi)部的比較(即同一條記錄的不同列的比較),效率非常高

>> 最后VW_SQ_2和外層的T表使用NL的方式進(jìn)行join,關(guān)聯(lián)字段為主鍵字段


執(zhí)行計(jì)劃出來(lái)以后,我們來(lái)估算一下這個(gè)SQL在執(zhí)行過(guò)程中的“訪問(wèn)公式”:

總的訪問(wèn)過(guò)程 = S表全掃 + T表全掃 + S表全掃 + VW_SQ_2記錄數(shù) *(1個(gè)T表主鍵索引塊 + 1個(gè)T表數(shù)據(jù)塊)


4.7 別忘了”set“


原語(yǔ)句的part2部分修改的跟老K預(yù)期的差不多,原語(yǔ)句part1部分與part2部分一致,那么我們簡(jiǎn)單的修改part1部分成part2部分就可以了嗎?顯然不是!通常,使用merge into語(yǔ)句能很方便的改寫(xiě)update語(yǔ)句,這里我們更能利用原語(yǔ)句part1和part2一致的特性,改寫(xiě)如下:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

>> 將語(yǔ)句改寫(xiě)為merge into的方式;

>> Merge的源與上一步改寫(xiě)的exists子句中的內(nèi)容一致,只是把與a的關(guān)聯(lián)關(guān)系提取到merge語(yǔ)句的on 部分;

>> 這樣改寫(xiě)后SQL執(zhí)行過(guò)程中也會(huì)鎖定需要修改的極少記錄。


這里改寫(xiě)后的執(zhí)行計(jì)劃與前面的update語(yǔ)句類(lèi)似,老K也就不單獨(dú)列出分析了。


Part 5

最后的總覽


最后我們?cè)賮?lái)看看我們改寫(xiě)后的語(yǔ)句及其執(zhí)行計(jì)劃:

語(yǔ)句如下:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

最終的執(zhí)行計(jì)劃:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

最終測(cè)試效果:


SQL優(yōu)化之基于SQL特征的改寫(xiě)

在測(cè)試環(huán)境,改寫(xiě)后的語(yǔ)句執(zhí)行了兩次,每次平均修改7.5條記錄,耗時(shí)4s,邏輯讀3.4w;細(xì)心的讀者可能能從最終的執(zhí)行計(jì)劃中看到,對(duì)T表的全表掃描也許可以避免等,由于篇幅原因以及測(cè)試環(huán)境的原因,老K沒(méi)有再在這里深究,畢竟老K分享的是SQL tuning的方法,而如何避免全表掃描以及如何分析避免了全表掃描后對(duì)SQL執(zhí)行效率提升的預(yù)估,相信讀者你一定已經(jīng)學(xué)到了,不妨自己做一個(gè)估算。


寫(xiě)在最后



讀到了最后,老K分享了什么,我們不妨來(lái)仔細(xì)回憶一番。


>> SQL分析過(guò)程中如何通過(guò)執(zhí)行計(jì)劃推算SQL執(zhí)行的邏輯讀

>> 針對(duì)CASE中的SQL如何通過(guò)添加索引來(lái)改善其執(zhí)行效率

>> 針對(duì)CASE中的SQL通過(guò)使用NVL的方式進(jìn)行改寫(xiě),它在什么場(chǎng)景下是合適的,什么情況下是不合適的。

>> 怎樣通過(guò)添加冗余關(guān)聯(lián)來(lái)引導(dǎo)數(shù)據(jù)庫(kù)生成我們想要的執(zhí)行計(jì)劃

>> 怎樣使用merge語(yǔ)法來(lái)改寫(xiě)update語(yǔ)句


最后,老K再一次強(qiáng)調(diào),在SQLtunning的過(guò)程中最重要的是優(yōu)化的思路和對(duì)問(wèn)題的思考方式,希望聰明的讀者已從這次分享中得到啟示。

編外:老K后來(lái)通過(guò)與應(yīng)用開(kāi)發(fā)團(tuán)隊(duì)溝通了解文中SQL的業(yè)務(wù)特征后,再次結(jié)合其業(yè)務(wù)特征改寫(xiě)了SQL,執(zhí)行效率再次得到了極大的提升,可見(jiàn),在SQLtunning的過(guò)程中,了解業(yè)務(wù)確實(shí)是非常重要的一環(huán)。

新聞標(biāo)題:SQL優(yōu)化之基于SQL特征的改寫(xiě)
本文URL:http://www.muchs.cn/article26/piepcg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航品牌網(wǎng)站制作、App開(kāi)發(fā)網(wǎng)站策劃、網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)