SqlServer执行计划
http://www.cnblogs.com/knowledgesea/p/5005163.html
?
序言
本篇主要目的有二:
1、看懂t-sql的執(zhí)行計(jì)劃,明白執(zhí)行計(jì)劃中的一些常識(shí)。
2、能夠分析執(zhí)行計(jì)劃,找到優(yōu)化sql性能的思路或方案。
如果你對(duì)sql查詢優(yōu)化的理解或常識(shí)不是很深入,那么推薦幾篇博文給你:SqlServer性能檢測(cè)和優(yōu)化工具使用詳細(xì)?,sql語(yǔ)句的優(yōu)化分析,T-sql語(yǔ)句查詢執(zhí)行順序。
執(zhí)行計(jì)劃簡(jiǎn)介
1、什么是執(zhí)行計(jì)劃?
大哥提交的sql語(yǔ)句,數(shù)據(jù)庫(kù)查詢優(yōu)化器,經(jīng)過(guò)分析生成多個(gè)數(shù)據(jù)庫(kù)可以識(shí)別的高效執(zhí)行查詢方式。然后優(yōu)化器會(huì)在眾多執(zhí)行計(jì)劃中找出一個(gè)資源使用最少,而不是最快的執(zhí)行方案,給你展示出來(lái),可以是xml格式,文本格式,也可以是圖形化的執(zhí)行方案。
2、預(yù)估執(zhí)行計(jì)劃,實(shí)際執(zhí)行計(jì)劃
選擇語(yǔ)句,點(diǎn)擊上面其中一個(gè)執(zhí)行計(jì)劃,預(yù)估執(zhí)行計(jì)劃可以立即顯示,而實(shí)際執(zhí)行計(jì)劃則需要執(zhí)行sql語(yǔ)句后出現(xiàn)。預(yù)估執(zhí)行計(jì)劃不等于實(shí)際執(zhí)行計(jì)劃,但是絕大多數(shù)情況下實(shí)際的執(zhí)行計(jì)劃跟預(yù)估執(zhí)行計(jì)劃都是一致的。統(tǒng)計(jì)信息變更或者執(zhí)行計(jì)劃重編譯等情況下,會(huì)造成不同。
3、為什么要讀懂執(zhí)行計(jì)劃
首先執(zhí)行計(jì)劃讓你知道你復(fù)雜的sql到底是怎么執(zhí)行的,有沒(méi)有按照你想的方案執(zhí)行,有沒(méi)有按照最高效的方式執(zhí)行,使用啦眾多索引的哪一個(gè),怎么排序,怎么合并數(shù)據(jù)的,有沒(méi)有造成不必要資源浪費(fèi)等等。官方數(shù)據(jù)顯示,執(zhí)行t-sql存在問(wèn)題,80%都可以在執(zhí)行計(jì)劃中找到答案。
4、針對(duì)圖形化執(zhí)行計(jì)劃分析
執(zhí)行計(jì)劃,可以以文本,xml,圖形化展示出來(lái)。本騙主要以圖形化執(zhí)行計(jì)劃主導(dǎo)進(jìn)行分析,然而執(zhí)行計(jì)劃中包含78個(gè)可用的操作符,本篇也只能對(duì)常用的進(jìn)行分析,常用的幾乎就包含你日常所有的了。Msdn上有圖片介紹:https://msdn.microsoft.com/zh-cn/library/ms175913(v=sql.90).aspx
5、怎么看執(zhí)行計(jì)劃
圖形化執(zhí)行計(jì)劃是從上到下從又到左看的。
6、清除緩存的執(zhí)行計(jì)劃
dbcc freeprocache
dbcc flushprocindb(db_id)
看懂圖形化執(zhí)行計(jì)劃
1、連線
1、越粗表示掃描影響的行數(shù)愈多。
2、Actual Number of Rows ?掃描中實(shí)際影響的的行數(shù)。
3、Estimated?Number of Rows 預(yù)估掃描影響的行數(shù)。
4、Estimated row size?操作符生成的行的估計(jì)大小(字節(jié))。
5、Estimated Data Size 預(yù)估影響的數(shù)據(jù)的大小。
2、Tooltips,當(dāng)前步驟執(zhí)行信息
??
Note:這個(gè)tips的信息告訴我們執(zhí)行的對(duì)象是什么,采用的操作操作是什么,查找的數(shù)據(jù)是什么,使用的索引是什么,排序與否,預(yù)估cpu、I/O、影響行數(shù),實(shí)際行數(shù)等信息。具體參數(shù)清單參見(jiàn)msdn:https://msdn.microsoft.com/zh-cn/library/ms178071(v=sql.90).aspx
3、Table Scan(表掃描)
當(dāng)表中沒(méi)有聚集索引,又沒(méi)有合適索引的情況下,會(huì)出現(xiàn)這個(gè)操作。這個(gè)操作是很耗性能的,他的出現(xiàn)也意味著優(yōu)化器要遍歷整張表去查找你所需要的數(shù)據(jù)。
4、Clustered Index Scan(聚集索引掃描)、Index Scan(非聚集索引掃描)
?
這個(gè)圖標(biāo)兩個(gè)操作都可以使用,一個(gè)聚集索引掃描,一個(gè)是非聚集索引掃描。
聚集索引掃描:聚集索引的數(shù)據(jù)體積實(shí)際是就是表本身,也就是說(shuō)表有多少行多少列,聚集所有就有多少行多少列,那么聚集索引掃描就跟表掃描差不多,也要進(jìn)行全表掃描,遍歷所有表數(shù)據(jù),查找出你想要的數(shù)據(jù)。
非聚集索引掃描:非聚集索引的體積是根據(jù)你的索引創(chuàng)建情況而定的,可以只包含你要查詢的列。那么進(jìn)行非聚集索引掃描,便是你非聚集中包含的列的所有行進(jìn)行遍歷,查找出你想要的數(shù)據(jù)。
5、Key Lookup(鍵值查找)
首先需要說(shuō)的是查找,查找與掃描在性能上完全不是一個(gè)級(jí)別的,掃描需要遍歷整張表,而查找只需要通過(guò)鍵值直接提取數(shù)據(jù),返回結(jié)果,性能要好。
當(dāng)你查找的列沒(méi)有完全被非聚集索引包含,就需要使用鍵值查找在聚集索引上查找非聚集索引不包含的列。
6、RID Lookoup(RID查找)
?
跟鍵值查找類似,只不過(guò)RID查找,是需要查找的列沒(méi)有完全被非聚集索引包含,而剩余的列所在的表又不存在聚集索引,不能鍵值查找,只能根據(jù)行表示Rid來(lái)查詢數(shù)據(jù)。
7、Clustered Index Seek(聚集索引查找)、Index Seek(非聚集索引查找)
聚集索引查找和非聚集索引查找都是使用該圖標(biāo)。
聚集索引查找:聚集索引包含整個(gè)表的數(shù)據(jù),也就是在聚集索引的數(shù)據(jù)上根據(jù)鍵值取數(shù)據(jù)。
非聚集索引查找:非聚集索引包含創(chuàng)建索引時(shí)所包含列的數(shù)據(jù),在這些非聚集索引的數(shù)據(jù)上根據(jù)鍵值取數(shù)據(jù)。
8、Hash join? ?三種物理連接merge、Hash、Loop 模型:https://blog.csdn.net/hzp666/article/details/107847358
?
這個(gè)圖標(biāo)有兩種地方用到,一種是表關(guān)聯(lián),一種是數(shù)據(jù)聚合運(yùn)算時(shí)。
在分別說(shuō)這兩種運(yùn)算的前面,我先說(shuō)說(shuō)Hashing(編碼技術(shù))和Hash Table(數(shù)據(jù)結(jié)構(gòu))。
Hashing:在數(shù)據(jù)庫(kù)中根據(jù)每一行的數(shù)據(jù)內(nèi)容,轉(zhuǎn)換成唯一符號(hào)格式,存放到臨時(shí)哈希表中,當(dāng)需要原始數(shù)據(jù)時(shí),可以給還原回來(lái)。類似加密解密技術(shù),但是他能更有效的支持?jǐn)?shù)據(jù)查詢。
Hash Table:通過(guò)hashing處理,把數(shù)據(jù)以key/value的形式存儲(chǔ)在表格中,在數(shù)據(jù)庫(kù)中他被放在tempdb中。
接下來(lái),來(lái)說(shuō)說(shuō)Hash Math的表關(guān)聯(lián)跟行數(shù)據(jù)聚合是怎么操作運(yùn)算的。
表關(guān)聯(lián):
如上圖,關(guān)聯(lián)兩個(gè)數(shù)據(jù)集時(shí),Hash Match會(huì)把其中較小的數(shù)據(jù)集,通過(guò)Hashing運(yùn)算放入HashTable中,然后一行一行的遍歷較大的數(shù)據(jù)集與HashTable進(jìn)行相應(yīng)的匹配拉取數(shù)據(jù)。
數(shù)據(jù)聚合:當(dāng)查詢中需要進(jìn)行Count/Sum/Avg/Max/Min時(shí),數(shù)據(jù)可能會(huì)采用把數(shù)據(jù)先放在內(nèi)存中的HashTable中然后進(jìn)行運(yùn)算。
9、Loops Join
這個(gè)操作符號(hào),把兩個(gè)不同列的數(shù)據(jù)集匯總到一張表中。提示信息中的Output List中有兩個(gè)數(shù)據(jù)集,下面的數(shù)據(jù)集(inner set)會(huì)一一掃描與上面的數(shù)據(jù)集(out set),直到掃描完為止,這個(gè)操作才算是完成。
10、Merge Join
這種關(guān)聯(lián)算法是對(duì)兩個(gè)已經(jīng)排過(guò)序的集合進(jìn)行合并。如果兩個(gè)聚合是無(wú)序的則將先給集合排序再進(jìn)行一一合并,由于是排過(guò)序的集合,左右兩個(gè)集合自上而下合并效率是相當(dāng)快的。
11、Sort(排序)
對(duì)數(shù)據(jù)集合進(jìn)行排序,需要注意的是,有些數(shù)據(jù)集合在索引掃描后是自帶排序的。
12、Filter(篩選)
根據(jù)出現(xiàn)在having之后的操作運(yùn)算符,進(jìn)行篩選
13、Computer Scalar
?
在需要查詢的列中需要自定義列,比如count(*) as cnt ,select name+''+age 等會(huì)出現(xiàn)此符號(hào)。
根據(jù)執(zhí)行計(jì)劃細(xì)節(jié)要做的優(yōu)化操作
這里會(huì)有很多建議給出,我不一一舉例了,給出幾個(gè)示例,想做到優(yōu)化行家,多的還需要大家去悟去理解。
1、如果select * 通常情況下聚集索引會(huì)比非聚集索引更優(yōu)。
2、如果出現(xiàn)Nested Loops,需要查下是否需要聚集索引,非聚集索引是否可以包含所有需要的列。
3、Hash Match連接操作更適合于需要做Hashing算法集合很小的連接。
4、Merge Join時(shí)需要檢查下原有的集合是否已經(jīng)有排序,如果沒(méi)有排序,使用索引能否解決。
5、出現(xiàn)表掃描,聚集索引掃描,非聚集索引掃描時(shí),考慮語(yǔ)句是否可以加where限制,select * 是否可以去除不必要的列。
6、出現(xiàn)Rid查找時(shí),是否可以加索引優(yōu)化解決。
7、在計(jì)劃中看到不是你想要的索引時(shí),看能否在語(yǔ)句中強(qiáng)制使用你想用的索引解決問(wèn)題,強(qiáng)制使用索引的辦法Select CluName1,CluName2 from Table with(index=IndexName)。
8、看到不是你想要的連接算法時(shí),嘗試強(qiáng)制使用你想要的算法解決問(wèn)題。強(qiáng)制使用連接算法的語(yǔ)句:select * from t1 left join t2 on t1.id=t2.id option(Hash/Loop/Merge Join)
9、看到不是你想要的聚合算法是,嘗試強(qiáng)制使用你想要的聚合算法。強(qiáng)制使用聚合算法的語(yǔ)句示例:select ?age ,count(age) as cnt from t1 group by age ?option(order/hash group)
10、看到不是你想要的解析執(zhí)行順序是,或這解析順序耗時(shí)過(guò)大時(shí),嘗試強(qiáng)制使用你定的執(zhí)行順序。option(force order)
11、看到有多個(gè)線程來(lái)合并執(zhí)行你的sql語(yǔ)句而影響到性能時(shí),嘗試強(qiáng)制是不并行操作。option(maxdop 1)
12、在存儲(chǔ)過(guò)程中,由于參數(shù)不同導(dǎo)致執(zhí)行計(jì)劃不同,也影響啦性能時(shí)嘗試指定參數(shù)來(lái)優(yōu)化。option(optiomize for(@name='zlh'))
13、不操作多余的列,多余的行,不做務(wù)必要的聚合,排序。
總結(jié)
以上是生活随笔為你收集整理的SqlServer执行计划的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SuperMemo UX 添加笔记 Ct
- 下一篇: 请设计输出实数的格式,包括:(1)一行输