亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 數據庫 > SQL Server > 正文

SQL Server調優系列基礎篇(子查詢運算總結)

2024-08-31 00:55:04
字體:
來源:轉載
供稿:網友
SQL Server調優系列基礎篇(子查詢運算總結)

前言

前面我們的幾篇文章介紹了一系列關于運算符的介紹,以及各個運算符的優化方式和技巧。其中涵蓋:查看執行計劃的方式、幾種數據集常用的連接方式、聯合運算符方式、并行運算符等一系列的我們常見的運算符。有興趣的童鞋可以點擊查看。

本篇我們介紹關于子查詢語句的一系列內容,子查詢一般是我們形成復雜查詢的一些基礎性操作,所以關于子查詢的應用方式就非常重要。

廢話少說,開始本篇的正題。

技術準備

數據庫版本為SQL Server2008R2,利用微軟的一個更簡潔的案例庫(Northwind)進行分析。

一、獨立的子查詢方式

所謂的獨立的子查詢方式,就是說子查詢和主查詢沒有相關性,這樣帶來的好處就是子查詢不依賴于外部查詢,所以可以獨立外部查詢而被評估,形成自己的執行計劃執行。

舉個例子

SELECT O1.OrderID,O1.FreightFROM Orders O1WHERE O1.Freight>(   SELECT AVG(O2.Freight)   FROM Orders O2)

這句SQL執行的目標是查詢訂單中運費大于平均運費數的訂單。

這里提取平均運費的子句就是一個完全獨立的子查詢,完全不依賴主查詢而獨立執行。同時這里我們這里利用利用一個標量計算(AVG),因此正好返回一行。

查看一下該語句的查詢計劃:

這個查詢計劃沒啥好介紹的,關于子查詢的執行計劃形成可以參照我的第二篇:SQL Server調優系列基礎篇(常用運算符總結)

不過這里需要提示一下就是,關于流聚合和計算標量形成的結果值(AVG)只包含一個結果值,所以該語句能正常的執行。

我們再來看另外一種情況

SELECT O.OrderIDFROM Orders OWHERE O.CustomerID=(   SELECT C.CustomerID   FROM Customers C   WHERE C.ContactName=N'Maria Anders')

該語句的也是獲取名字為'Maria Anders'的顧客有多少訂單。這句T-SQL語句能否執行的前提是在顧客表里存不存在同名的“'Maria Anders'”顧客,如果存在同名情況,該語句就不能正確執行,而如果恰巧只有一名顧客為'Maria Anders',則能正常執行。

我們來分析一下對于這種執行的時候才能判斷能否正確執行的SQL Server如何判斷的

在這里出現了一個新的運算符,名字是:斷言。我們用文本執行計劃來查看一下,這個運算符的主要功能是什么

經過上面的分析,我們已經分析出了上面的“斷言”運算符的作用,因為我們的子查詢語句不能保證返回的結果為一行,所以,這里引入了一個斷言運算符來做判斷。

所以,斷言的作用就是根據下文的條件,判斷子查詢句的查詢結果是否滿足主語句的查詢要求。

如果,斷言發現子語句不滿足,就會直接報錯,比如上面的ExPR1005>1

并且,斷言運算符還經常用來檢測其它條件是否滿足,比如:約束條件、參數類型、值長度等。

其實,這里斷言要解決的問題就是判斷我們的篩選條件中ContactName中的值是否存在重復值的,對于這種判斷相對性能消耗還是比較小的,有時候對于別的復雜的斷言操作需要消耗大量資源,所以我們就可以根據適當情況情況避免斷言操作。

比如,上面的語句我們可以明確的告訴SQL Server在表Customers中ContactName列就不存在重復值,它就不需要斷言了。我們在上面建立一個:唯一、非聚集索引實現

CREATE UNIQUE INDEX ContactNameIndex ON Customers(ContactName)GOSELECT O.OrderIDFROM Orders OWHERE O.CustomerID=(   SELECT C.CustomerID   FROM Customers C   WHERE C.ContactName=N'Maria Anders')drop index Customers.ContactNameIndexGO

經過我們唯一非聚集索引的提示,SQL Server已經明確的知道我們的子查詢語句不會返回多行的情況,所以就去掉了斷言操作。

二、相關的子查詢方式

相比上面的獨立子查詢方式,這里的相關的子查詢方式相對復雜點,就是我們的子查詢依賴于主查詢的的結果,對于這種子查詢就不能單獨執行。

我們來看個這樣的子查詢例子

SELECT O1.OrderIDFROM Orders O1WHERE O1.Freight>(   SELECT AVG(O2.Freight)   FROM Orders O2   WHERE O2.OrderDate<O1.OrderDate)

這個語句就是返回之前訂單中運費量大于平均值的頂點編號。

語句很簡單的邏輯,但是這里面的子查詢就依賴于主查詢的結果項,篩選條件中WHERE O2.OrderDate<O1.OrderDate,所以這個子查詢就不能獨立運行。

我們來看一下這個語句的執行計劃

這里的查詢計劃有出現了一個新的運算符:索引假脫機。

其實,關于索引假脫機的作用主要是用于子查詢的獨立運行,因為我們知道這里的子查詢的查詢條件是依賴于主查詢的,所以,這里想運行的話就的先提前獲取出主查詢的結果項,而這里獲取的主查詢的結果項需要一個中間表來暫存,這里暫存的工具就是:(索引池)Index Spool,而對這個索引池的操作,比如:新建、增加等操作就是上面我們所標示的“索引假脫機”了。

索引假脫機分為兩種:Eager Spool和Lazy Spool,其實簡單點講就是需不需要立刻將結果存入Index Spool里面,還是通過延遲操作。

而這里形成的索引池(Index Spool)是存放于系統的臨時庫Tempdb中。

我們通過文本查詢計劃,來分析下兩個索引假脫機里面的值是什么

經過上面的分析,我們已經看到了,里面的Eager Spool是和主查詢比較形成的結果值,因為這個必須要及時的形成,以便于子查詢的進行,所以它的類型為Eager Spool,

而子查詢外面的那個Index Spool為Lazy Spool,這個結果項的保存不需要那么及時了,這個保存的就是子查詢的形成的結果項了,就是相對每個訂單運費的平均值。

我上面的分析,希望各位看官能看懂了。

其實,關于這個Index Spool的設計的目的,完全為了就是提升性能,因為我們知道上面的查詢語句每個子查詢的進行,都必須回調主查詢的結果,所以為了避免每次都回調,就采用了Index Spool進行暫存,而這個Index Spool存儲的位置就是Tempdb,所以Tempdb運行的快慢直接關乎這種查詢語句的性能。

這也是我們為什么強調大并發的數據庫搭建,建議將Tempdb庫單獨存放于高性能的硬件環境中。

曬曬聯機叢書中關于假脫機數據運算符官方介紹:

Index Spool物理運算符在Argument列中包含 SEEK:() 謂詞。Index Spool運算符掃描其輸入行,將每行的副本放置在隱藏的假脫機文件(存儲在tempdb數據庫中且只在查詢的生存期內存在)中,并為這些行創建非聚集索引。這樣可以使用索引的查找功能來僅輸出那些滿足 SEEK:() 謂詞的行。

如果重繞該運算符(例如通過Nested Loops運算符重繞),但不需要任何重新綁定,則將使用假脫機數據,而不用重新掃描輸入。

跟索引脫機類似的還有一個相似的運算符:表脫機,其功能類似,表脫機存儲的應該是鍵值列,而表脫機則是存儲的是多列數據了。

來看例子

SELECT O1.OrderID,O1.FreightFROM Orders O1WHERE O1.Freight>(   SELECT AVG(O2.Freight)   FROM Orders O2   WHERE O2.CustomerID=O1.CustomerID)

這個查詢和上面的類似,只不過是查詢的同一個客戶加入的超過所有訂單運費平均值的訂單。

此語句同樣不是獨立的子查詢語句,每個子查詢的結果的形成都需要依賴主查詢的結果項,為了加快速度,提升性能,SQL Server會將主表查詢的的結果項暫存到一張臨時表中,這個表就被稱為表脫機

我們來看這句話的執行計劃:

這里就用到了一個表脫機的運算符,這個運算符的作用就是用來暫存后面掃描獲取的結果集合,用于下面的子查詢的應用

這個表脫機形成的結果項也是存儲到臨時庫Tempdb中,所以它的應用和前面提到的索引脫機類似。

上面的執行計劃中,還提到了一個新的運算符:段(Segment)

這個運算符的解釋是:Segment既是一個物理運算符,也是一個邏輯運算符。它基于一個或多個列的值將輸入集劃分成多個段。這些列顯示為Segment運算符中的參數。然后運算符每次輸出一個段。

其實作用就是將結果進行匯總整理,將相同值匯聚到一起,跟排序一樣,只不過這里可以對多列值進行匯聚。

我們再來看一個例子,加深 一下關于段運算的作用

SELECT CustomerID,O1.OrderID,O1.FreightFROM Orders O1WHERE O1.Freight=(   SELECT MAX(O2.Freight)   FROM Orders O2   WHERE O2.CustomerID=O1.CustomerID)

這個語句查詢的是:每個顧客所產生的最大運費的訂單數據。

以上語句,如果理解起來有難度,我們可以變通以下的相同邏輯的T-SQL語句,相同的邏輯

SELECT O1.CustomerID,O1.OrderID,O1.Freight FROM Orders O1INNER JOIN(    SELECT CustomerID,max(Freight) Freight    FROM Orders    GROUP BY CustomerID) AS O2ON O1.CustomerID=O2.CustomerIDAND O1.Freight=O2.Freight

先根據客戶編號分組,然后獲取出最大的運費項,再關聯主表獲取訂單信息。

以上兩種語句生成的相同的查詢計劃:

這里我們來解釋一下,SQL Server的強大之處,也是段運算符使用的最佳方式。

本來這句話要實現,按照邏輯需要有一個嵌套循環連接,參照上面的方式,使用表脫機的方式進行數據的獲取。

但是,我們這句話獲取的結果項是每個顧客的最大運費的訂單明細項,而且CustomerID列作為輸出項,所以這里采用了,先按照運費列(Freight)排序,

然后采用段運算符進行將每個顧客相同的數據匯聚到一起,然后再輸出每個顧客的前一列(TOP 1)獲取的就是最每個顧客的運費最大的訂單項。

省去了任何的表假脫機、索引假脫機、關聯連接等一系列復雜的操作。

SQL Server看來這種智能化的操作還是挺強的。

我們再來分析SQL Server關于子查詢這塊的智能特性,因為經過上面的分析通過對比,相關的子查詢語句在運行時需要更多的消耗:

1、有時候需要通過索引假脫機(Index Spool)、表脫機(Table Spool)進行中間結果項的暫存,而這一過程的中間項需要創建、增加、刪除、銷毀等操作都需要消耗大量的內存和CPU

2、關于相關子查詢中以上提到的中間項的形成都是位于Tempdb臨時庫中,有時候會增大Tempdb的空間,增加Tempdb庫的消耗、頁爭用等問題。

所以,要避免上面的問題,最好的方式是避免使用相關子查詢,盡量使用獨立子查詢進行操作。

當然,SQL Server同樣提供了自動轉換的功能,智能的去分析語句,避免相關的子查詢操作進行:

來看一個稍差的寫法:

SELECT o.OrderID FROM Orders OWHERE EXISTS(   SELECT c.CustomerID   FROM  Customers C   WHERE C.City=N'Londom' AND C.CustomerID=O.CustomerID)

上面的語句,我們寫的是相關的子查詢操作,但是在執行計劃中形成的確實獨立的子查詢,這樣從而避免相關的子查詢所帶來的性能消耗。

其實上面語句,相對好的寫法是如下

SELECT o.OrderID FROM Orders OWHERE O.CustomerID IN(   SELECT c.CustomerID   FROM  Customers C   WHERE C.City=N'Londom')

這樣所形成的就是完全獨立的子查詢,這也是SQL Server要執行的意圖。所以這個語句形成的查詢計劃是和上面的查詢計劃一樣。

這里的優化全部得益于SQL Server的智能化。

但是我們在寫語句的時候,需要自己了解,掌握好,這樣才能寫出高效的T-SQL語句。

參考文獻

  • 微軟聯機叢書邏輯運算符和物理運算符引用
  • 參照書籍《SQL.Server.2005.技術內幕》系列

結語

本篇篇幅有點長,但是介紹的子查詢內容也還不是很全,后續慢慢的補充上,我們寫的SQL語句中很多都涉及到子查詢,所以這塊應用還是挺普遍的。到本篇文章關于日常調優的T-SQL中的查詢語句經常用到的一些運算符基本介紹全了,當然,還有一些別的增刪改一系列的運算符,這些日常生活中我們一般不采用查詢計劃調優,后續我們的文章會將這些運算符也添加上,以供參考之用。

在完成本系列關于查詢計劃相關的調優之后,我打算將數據庫有關統計信息這塊也做一個詳細的分析介紹。因為統計信息是支撐SQL Server評估最優執行計劃的最重要的決策點,

所以統計信息的重要性不言而喻。有興趣的童鞋可以提前關注。

關于SQL Server性能調優的內容涉及面很廣,后續文章中依次展開分析。

有問題可以留言或者私信,隨時恭候有興趣的童鞋加入SQL SERVER的深入研究。共同學習,一起進步。

文章最后給出上幾篇的連接,看來有必要整理一篇目錄了.....

SQL Server調優系列基礎篇

SQL Server調優系列基礎篇(常用運算符總結)

SQL Server調優系列基礎篇(聯合運算符總結)

SQL Server調優系列基礎篇(并行運算總結)

SQL Server調優系列基礎篇(并行運算總結篇二)

SQL Server調優系列基礎篇(索引運算總結)

如果您看了本篇博客,覺得對您有所收獲,請不要吝嗇您的“推薦”。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美丰满老妇厨房牲生活| 国产成人激情小视频| 欧美巨猛xxxx猛交黑人97人| 亚洲福利在线观看| 欧美性资源免费| 久久成人精品电影| 亚洲老头老太hd| 91精品中国老女人| 奇米四色中文综合久久| 欧洲一区二区视频| 国产精品老女人视频| 国产精品96久久久久久| 中文字幕亚洲一区| 日韩欧美有码在线| 日韩一区二区三区国产| 欧美丝袜一区二区三区| 亚洲一区二区三区乱码aⅴ| 日韩av中文字幕在线免费观看| 亚洲在线第一页| 欧美野外猛男的大粗鳮| 中文国产亚洲喷潮| 91超碰中文字幕久久精品| 久久免费视频这里只有精品| 日韩美女视频免费在线观看| 亚洲一区二区三区毛片| 色偷偷亚洲男人天堂| 成人av电影天堂| 日本韩国在线不卡| 日韩中文字幕视频在线观看| 性色av一区二区三区在线观看| 欧美人交a欧美精品| 亚洲国产精品福利| 日韩免费在线观看视频| 中文字幕日韩综合av| 久久精品99国产精品酒店日本| 伊人久久综合97精品| 日本久久久久久久久久久| 激情亚洲一区二区三区四区| 亚洲韩国日本中文字幕| 亚洲精品免费av| 中文字幕免费国产精品| 日韩av综合中文字幕| 国产精品美女999| 一区二区三区无码高清视频| 91天堂在线观看| 亚洲人成五月天| 欧美电影在线免费观看网站| 亚州精品天堂中文字幕| 国产精品69精品一区二区三区| 91中文字幕在线观看| 国产不卡精品视男人的天堂| 成人性生交大片免费看小说| 亚洲天堂男人天堂女人天堂| 久久精品视频在线播放| 国产日本欧美在线观看| 日本sm极度另类视频| 美女扒开尿口让男人操亚洲视频网站| 欧美一级淫片videoshd| 精品国产精品三级精品av网址| 亚洲午夜久久久久久久| 国产午夜精品视频免费不卡69堂| 国产免费一区二区三区在线观看| 中日韩美女免费视频网站在线观看| 欧美激情在线一区| 欧美激情视频一区二区| 97涩涩爰在线观看亚洲| 亚洲成人av资源网| 北条麻妃在线一区二区| 在线观看免费高清视频97| 午夜精品久久久久久久99黑人| 97国产在线视频| 黑人巨大精品欧美一区二区免费| 日韩中文字幕免费视频| 欧美一区二区三区图| 国产成人鲁鲁免费视频a| 亚洲第一免费网站| 国产精品久久久久久婷婷天堂| 日韩在线观看网址| 中文字幕亚洲激情| 欧美性猛交xxxx黑人猛交| 国产成人精品免高潮费视频| 亚洲欧美另类中文字幕| 久久久噜久噜久久综合| 日韩av电影院| 另类色图亚洲色图| 国产亚洲欧美日韩一区二区| 亚洲黄色成人网| 国产v综合ⅴ日韩v欧美大片| 中文字幕在线看视频国产欧美在线看完整| 欧美一乱一性一交一视频| 精品成人国产在线观看男人呻吟| 茄子视频成人在线| 亚洲精品小视频在线观看| 欧美在线日韩在线| 91色在线视频| 久久99视频免费| 精品国产老师黑色丝袜高跟鞋| 欧美精品一区二区免费| 亚洲精品中文字幕女同| 欧美在线视频免费播放| 欧美老肥婆性猛交视频| 成人精品一区二区三区电影免费| 亚洲天堂色网站| 中文欧美在线视频| 亚洲精品国产精品国产自| 国产精品电影网站| 91在线免费网站| 91久久中文字幕| 久久久久久久久久久久av| 2019最新中文字幕| 国产精品第三页| 亚洲欧洲国产伦综合| 成人激情视频在线| 日韩av有码在线| 成人午夜小视频| 欧美激情第一页xxx| 久久久久久国产精品| 懂色av影视一区二区三区| 国产精品视频免费在线| 欧美视频裸体精品| 亚洲午夜激情免费视频| 国产精品久久久久久久久久小说| 亚洲男女自偷自拍图片另类| 国产偷国产偷亚洲清高网站| 日韩在线视频免费观看| 国产精品青青在线观看爽香蕉| 欧美激情一区二区三区在线视频观看| 最近的2019中文字幕免费一页| 日韩成人在线观看| 亚洲男人天堂网| 欧美激情视频网站| 国产成人精品av在线| 国产成人aa精品一区在线播放| 成人啪啪免费看| 国产精品三级在线| 狠狠躁18三区二区一区| 在线日韩日本国产亚洲| 国产精品免费久久久久影院| 亚洲成人av中文字幕| 91精品综合久久久久久五月天| 亚洲国产精品中文| 黄色91在线观看| 欧美电影在线观看高清| 日韩av影片在线观看| 日韩美女福利视频| 91免费看视频.| 亚洲毛茸茸少妇高潮呻吟| 国产精品夫妻激情| 国产福利视频一区二区| 中文字幕一区电影| 亚洲伊人成综合成人网| 欧洲中文字幕国产精品| 亚洲最新av在线| 亚洲欧美制服综合另类| 91青草视频久久| 成人免费大片黄在线播放| 欧美激情综合色综合啪啪五月| 日韩人在线观看| 精品美女国产在线| 国外成人免费在线播放| 久久久国产成人精品| 欧美大奶子在线| 国产精品日韩在线播放| 中文字幕视频在线免费欧美日韩综合在线看|