T-SQL | 你需要了解的执行计划
【T-SQL】|?作者?/ Edison Zhou
這是EdisonTalk的第297篇學(xué)習(xí)分享
T-SQL是ANSI和ISO SQL標(biāo)準(zhǔn)的MS SQL擴(kuò)展,其正式名稱為Transact-SQL,但一般程序員都稱其為T-SQL。本文是我學(xué)習(xí)《T-SQL查詢》一書的讀書筆記,為你講解執(zhí)行計(jì)劃是個(gè)什么鬼。
1關(guān)于執(zhí)行計(jì)劃
執(zhí)行計(jì)劃是優(yōu)化器生成的用于確定如何處理一個(gè)給定查詢的“工作計(jì)劃”。一個(gè)計(jì)劃包含一組運(yùn)算符,通常按照特定的順序來應(yīng)用這些運(yùn)算符。
此外,一些運(yùn)算符可以在它們之前的運(yùn)算符還在處理時(shí)被應(yīng)用(即不一定是完全串行),還有一些運(yùn)算符也有可能被應(yīng)用多次。
2圖形化執(zhí)行計(jì)劃
SSMS中的圖形化執(zhí)行計(jì)劃
在SSMS(SQL Server Management Studio)中,有兩種圖形化的執(zhí)行計(jì)劃可供選擇。一種是估計(jì)執(zhí)行計(jì)劃(Ctrl+L鍵),另一種是實(shí)際執(zhí)行計(jì)劃(Ctrl+M鍵)。兩種計(jì)劃通常都是一樣的,只是執(zhí)行時(shí)間點(diǎn)不同。估計(jì)查詢計(jì)劃是在查詢執(zhí)行之前生成,而實(shí)際執(zhí)行計(jì)劃則是在查詢輸出的同時(shí)得到的。
圖形化執(zhí)行計(jì)劃實(shí)例講解
Step1.示例查詢介紹
(1)假設(shè)我們有一張Orders表,里面有100w行訂單數(shù)據(jù),從2005年開始到2009年。
(2)待分析的查詢語句
-- 圖形化執(zhí)行計(jì)劃查詢示例 SELECT custid, empid, shipperid, COUNT(*) AS numorders FROM dbo.Orders WHERE orderdate >= '20080201'AND orderdate < '20080301' GROUP BY CUBE(custid, empid, shipperid); GOStep2.估計(jì)的執(zhí)行計(jì)劃查看(選中SQL語句按Ctrl+L)
當(dāng)我們將光標(biāo)移動(dòng)到某個(gè)運(yùn)算符上面時(shí),可以得到該運(yùn)算符返回的估計(jì)行數(shù)和開銷。箭頭的粗細(xì)與源運(yùn)算符返回的行數(shù)是成正比的。所以,重點(diǎn)關(guān)注比較粗的箭頭,它們可能預(yù)示著性能問題。
Step3.實(shí)際的執(zhí)行計(jì)劃(先選中“包括實(shí)際的執(zhí)行計(jì)劃”,再執(zhí)行該查詢,即可同時(shí)得到查詢的輸出和實(shí)際的計(jì)劃)
這時(shí)再把光標(biāo)移到某個(gè)運(yùn)算符,看到的會(huì)變?yōu)椤皩?shí)際行數(shù)”。
Step4.縮放到合適的大小
*.如果得到了一個(gè)無法適合屏幕顯示的計(jì)劃時(shí),可以使用一個(gè)很酷的功能,叫做縮放到合適大小。(點(diǎn)擊鼠標(biāo)右鍵出現(xiàn)菜單,選擇即可)
點(diǎn)擊后,執(zhí)行計(jì)劃會(huì)變?yōu)槿缦聢D所示:
Step5.執(zhí)行計(jì)劃是由運(yùn)算符組成的一個(gè)樹狀結(jié)構(gòu),在圖形化計(jì)劃中,是從右到左從上到下的順序來表示的。在這個(gè)例子中,聚集索引查找(Clustered Index Seek)是數(shù)據(jù)流的第一個(gè)運(yùn)算符,生成的輸出傳到樹中的下一個(gè)運(yùn)算符-表假脫機(jī)(Eager Spool),以此類推。
我們需要注意與每個(gè)運(yùn)算符相關(guān)聯(lián)的開銷百分比,這個(gè)值是某個(gè)運(yùn)算符的開銷占查詢?nèi)块_銷的百分比,由優(yōu)化器估算。這里,我們需要多留意一下百分比值比較高的運(yùn)算符,重點(diǎn)對(duì)這些運(yùn)算符進(jìn)行優(yōu)化。
此外,當(dāng)我們將光標(biāo)放在一個(gè)運(yùn)算符上面時(shí),其中有一項(xiàng)叫做“估計(jì)子樹大小(Estimated Subtree Cost)”,這個(gè)值代表從當(dāng)前運(yùn)算符開始的子樹的累計(jì)估計(jì)大小。比如,這里我們通過將光標(biāo)移動(dòng)到最左邊的SELECT運(yùn)算符,即根節(jié)點(diǎn),可以看到整個(gè)查詢的估計(jì)開銷(因?yàn)槠渥訕浯砹苏麄€(gè)查詢)。
比較多個(gè)查詢的開銷
圖形化執(zhí)行計(jì)劃的另一個(gè)有用的功能就是可以方便地比較多個(gè)查詢的開銷。
假設(shè)我們想比較以下幾個(gè)實(shí)現(xiàn)類似目標(biāo)的查詢的開銷:
SELECT custid, orderid, orderdate, empid, filler FROM dbo.Orders AS O1 WHERE orderid =(SELECT TOP (1) O2.orderidFROM dbo.Orders AS O2WHERE O2.custid = O1.custidORDER BY O2.orderdate DESC, O2.orderid DESC);SELECT custid, orderid, orderdate, empid, filler FROM dbo.Orders WHERE orderid IN (SELECT(SELECT TOP (1) O.orderidFROM dbo.Orders AS OWHERE O.custid = C.custidORDER BY O.orderdate DESC, O.orderid DESC) AS oidFROM dbo.Customers AS C );SELECT A.* FROM dbo.Customers AS CCROSS APPLY(SELECT TOP (1) O.custid, O.orderid, O.orderdate, O.empid, O.fillerFROM dbo.Orders AS OWHERE O.custid = C.custidORDER BY O.orderdate DESC, O.orderid DESC) AS A;WITH C AS (SELECT custid, orderid, orderdate, empid, filler,ROW_NUMBER() OVER(PARTITION BY custidORDER BY orderdate DESC, orderid DESC) AS nFROM dbo.Orders ) SELECT custid, orderid, orderdate, empid, filler FROM C WHERE n = 1; GO在SSMS中選中他們,并請(qǐng)求圖形化執(zhí)行計(jì)劃(估計(jì)的或?qū)嶋H的)。這里,我們將會(huì)得到如下圖所示的計(jì)劃。
建議點(diǎn)開看大圖
從圖中可以看到,在每個(gè)計(jì)劃頂部都會(huì)有一個(gè)百分比,表示該查詢的開銷占整個(gè)批處理總開銷的百分比,這里Query1=>34%,Query2=>19%,Query3=>28%,Query4=>20%,可以看出,Query1的查詢開銷最大,需要進(jìn)一步檢查其性能。
關(guān)于黃色窗口的各個(gè)屬性項(xiàng),具體可以參考:顯示圖形執(zhí)行計(jì)劃 (SQL Server Management Studio)
https://technet.microsoft.com/zh-cn/library/ms178071(v=sql.105).aspx
Ref參考資料
[美] Itzik Ben-Gan 著,《SQL Server 2008技術(shù)內(nèi)幕:T-SQL查詢》
????掃碼關(guān)注EdisonTalk
設(shè)為星標(biāo),不再失聯(lián)!
往期推文合集:2020年上半年推文合集
更多SQL文章:每天10分鐘T-SQL系列
總結(jié)
以上是生活随笔為你收集整理的T-SQL | 你需要了解的执行计划的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CAP-微服务间通信实践
- 下一篇: EFCore之SQL扩展组件Beetle