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

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

SQL Server 執行計劃的理解

2024-08-31 00:56:02
字體:
來源:轉載
供稿:網友

  要理解執行計劃,怎么也得先理解,那各種各樣的名詞吧。鑒于自己還不是很了解。本文打算作為只寫懂的,不懂的懂了才寫。

  在開頭要先說明,第一次看執行計劃要注意,SQL Server的執行計劃是從右向左看的。

  名詞解析:

  掃描:逐行遍歷數據。

  先建立一張表,并給大家看看大概是什么樣子的。

復制代碼
  CREATE TABLE Person(      Id int IDENTITY(1,1) NOT NULL,      Name nvarchar(50) NULL,      Age int NULL,      Height int NULL,      Area nvarchar(50) NULL,      MarryHistory nvarchar(10) NULL,      EducationalBackground nvarchar(10) NULL,      Address nvarchar(50) NULL,      InSiteId int NULL  ) ON [PRIMARY]復制代碼

  表中的數據14萬左右,大概類似下面這樣:

  

  此表,暫時沒有任何索引。

一、數據訪問操作

 1、表掃描

  表掃描:發生于堆表,并且沒有可用的索引可用時,會發生表掃描,表示整個表掃描一次。

  現在,我們來對此表執行一條簡單的查詢語句:

  SELECT * From Person WHERE Name = '公子'

  查看執行計劃如下:

  

  表掃描,顧名思義就是整張表掃描,找到你所需要的數據了。

 2、聚集索引掃描

  聚集索引掃描:發生于聚集表,也相當于全表掃描操作,但在針對聚集列的條件如(WHERE Id > 10)等操作時,效率會較好。

  下面我們在Id列來對此表加上一個聚集索引

  CREATE CLUSTERED INDEX IX_Id ON Person(Id)

  再次執行同樣的查詢語句:

  SELECT * From Person WHERE Name = '公子'

  執行計劃如下:

  

  為什么建的聚集索引在Id列,會對掃描有影響呢?更何況與Name條件也沒關系啊?

  其實,你加了聚集索引之后,表就由堆表變成了聚集表。我們知道聚集表的數據存在于聚集索引的葉級節點。因此,聚集掃描與表掃描其實差別不大,要說差別大,也得看where條件里是什么,以后返回的數據。就本條SQL語句而言,效率差別并不大。

  可以看看I/O統計信息:

  表掃描:

  

  聚集索引掃描:

  

  此處超出本文范疇了,效率不在本文考慮范圍內,本文只考慮的是,各種掃描的區別,以及為何會產生。

 3、聚集索引查找

  聚集索引查找:掃描聚集索引中特定范圍的行。

  看執行以下SQL語句:

  SELECT * FROM Person WHERE Id = '73164'

  執行計劃如下:

  

 4、索引掃描

  索引掃描:整體掃描非聚集索引。

  下面我們來添加一個聚集索引,并執行一條查詢語句:

  CREATE NONCLUSTERED INDEX IX_Name ON Person(Name)    --創建非聚集索引  SELECT Name FROM Person

  查看執行計劃如下:

  

  為什么此處會選擇索引掃描(非聚集索引)呢?

  因為此非聚集索引能夠覆蓋所需要的數據。如果非聚集索引不能覆蓋呢?例如,我們將SELECT改為SELECT *再來看看。

  

   好明顯,返回結果所包括的記錄太多,用非聚集索引反而不合算。因此使用了聚集索引。

  如果此時我們刪除聚集索引,再執行SELECT *看看。

  DROP INDEX Person.IX_Id

  

  而此時沒有聚集索引,所以只有使用表掃描。

 5、書簽查找

  前面關于索引的學習我們已經知道,當在非聚集索引中并非覆蓋和包含所需全部的列時,SQL Server會選擇,直接進行聚集索引掃描獲得數據,還是先去非聚集索引找到聚集索引鍵,然后利用聚集索引找到數據。

  下面來看一個書簽查找的示例:

  SELECT * FROM Person WHERE Name = '胖胖'  --Name列有非聚集索引

  執行計劃如下:

  

  上面的過程可以理解為:首先通過非聚集索引找到所求的行,但這個索引并不包含所有的列,因此還要額外去基本表中找到這些列,因此要進行鍵查找,如果基本表是以堆進行組織的,那么這個鍵查找(Key Lookup)就會變成RID查找(RID Lookup),鍵查找和RID查找統稱為書簽查找。不過有時當非聚集索引返回的行數過多時,SQL Server可能會選擇直接進行聚集索引掃描了。

二、流聚合操作

 1、流聚合

  流聚合:在相應排序的流中,計算多組行的匯總值。

  所有的聚合函數(如COUNT(),MAX())都會有流聚合的出現,但是其不會消耗IO,只有消耗CPU。

   例如執行以下語句:

  SELECT MAX(Age) FROM Person

  查看執行計劃如下:

  

 2、計算標量

  計算標量:根據行中的現有值計算新值。比如COUNT()函數,多一行,行數就加1咯。

  除MIN和MAX函數之外的聚合函數都要求流聚合操作后面跟一個計算標量。

  SELECT COUNT(*) FROM Person

  查看執行計劃如下:

  

3、散列聚合(哈希匹配)

  對于加了Group by的子句,因為需要數據按照group by 后面的列有序,就需要Sort來保證排序。注意,Sort操作是占用內存的操作,當內存不足時還會去占用tempdb。SQL Server總是會在Sort操作和散列匹配中選擇成本最低的。

  SELECT Height,COUNT(Id) FROM Person    --查出各身高的認輸  GROUP BY Height

  執行計劃如下:

  

  對于數據量比較大時,SQL Server選擇的是哈希匹配。

  在內存中建立好散列表后,會按照group by后面的值作為鍵,然后依次處理集合中的每條數據,當鍵在散列表中不存在時,向散列表添加條目,當鍵已經在散列表中存在時,按照規則(規則是聚合函數,比如Sum,avg什么的)計算散列表中的值(Value)。

 4、排序

   當數據量比價少時,例如執行以下語句,新建一個只有數十條記錄的與Person一樣的表。

  SELECT * INTO Person2 FROM Person2  WHERE Id < 100

  再來執行同樣的查詢語句:

  SELECT Height,COUNT(Id) FROM Person2    --只是表換成了數據量比較少的表  GROUP BY Height

  執行計劃如下:

  

三、連接

  當多表連接時(包括書簽查找,索引之間的連接),SQL Server會采用三類不同的連接方式:循環嵌套連接,合并連接,散列連接。這幾種連接格式有適合自己的場景,不存在哪個更好的說法。

   新建兩張表如下

   

   這是一個簡單的新聞,欄目結構。

 1、嵌套循環

  先來看一個簡單的Inner Join查詢語句

  SELECT * FROM Nx_Column AS C  INNER JOIN Nx_Article AS A  ON A.ColumnId = C.ColumnId

  執行計劃如下:

  

  循環嵌套連接的圖標同樣十分形象,處在上面的外部輸入(Outer input),這里也就是聚集索引掃描。和處在下面的內部輸入(Inner Input),這里也就是聚集索引查找。外部輸入僅僅執行一次,根據外部輸入滿足Join條件的每一行,對內部輸入進行查找。這里由于是7行,對于內部輸入執行7次。

   

  根據嵌套循環的原理不難看出,由于外部輸入是掃描,內部輸入是查找,當兩個Join的表外部輸入結果集比較小,而內部輸入所查找的表非常大時,查詢優化器更傾向于選擇循環嵌套方式。

 2、合并連接

  不同于循環嵌套的是,合并連接是從每個表僅僅執行一次訪問。從這個原理來看,合并連接要比循環嵌套要快了不少。

  從合并連接的原理不難想象,首先合并連接需要雙方有序.并且要求Join的條件為等于號。因為兩個輸入條件已經有序,所以從每一個輸入集合中取一行進行比較,相等的返回,不相等的舍棄,從這里也不難看出Merge join為什么只允許Join后面是等于號。從圖11的圖標中我們可以看出這個原理。

  SELECT * FROM Nx_Column AS C  INNER JOIN    Nx_Article AS A  ON A.ColumnId = C.ColumnId  OPTION(MERGE join)

  執行計劃如下:

  

  如果輸入數據的雙方無序,則查詢分析器不會選擇合并連接,我們也可以通過索引提示強制使用合并連接,為了達到這一目的,執行計劃必須加上一個排序步驟來實現有序。這也是上述SQL語句為什么要加OPTION(MERGE join)的原因。上述對Article表的ColumnId列進行了排序。

 3、哈希連接

  散列連接同樣僅僅只需要只訪問1次雙方的數據。散列連接通過在內存中建立散列表實現。這比較消耗內存,如果內存不足還會占用tempdb。但并不像合并連接那樣需要雙方有序。

  要進行下面這兩個實現,得把兩個列的聚集索引不要建在ColumnId列,否則不會采用哈希連接。

  ALTER TABLE PK_Nx_Column DROP CONSTRAINT PK_Nx_Column    --刪除主鍵  DROP INDEX Nx_Column.PK_Nx_Column    --刪除聚集索引  CREATE CLUSTERED INDEX IX_ColumnName ON Nx_Column(ColumnName)    --創建聚集索引  --這里再設置回主鍵就可以了,有了聚集索引,就不能隨主鍵默認建啦

  還要刪除另外一個表Article的聚集索引哦。

  然后執行以下查詢:

  SELECT * FROM Nx_Column AS C  INNER JOIN    Nx_Article AS A  ON A.ColumnId = C.ColumnId

  執行計劃如下:

  

    要刪除掉聚集索引,否則兩個有序輸入SQL Server會選擇代價更低的合并連接。SQL Server利用兩個上面的輸入生成哈希表,下面的輸入來探測,可以在屬性窗口看到這些信息,如圖15所示。

    通常來說,所求數據在其中一方或雙方沒有排序的條件達成時,會選用哈希匹配。

四、并行

  當多個表連接時,SQL Server還允許在多CPU或多核的情況下允許查詢并行,這樣無疑提高了效率。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲午夜av久久乱码| www.精品av.com| 亚洲已满18点击进入在线看片| 日韩电影大全免费观看2023年上| 精品露脸国产偷人在视频| www.亚洲男人天堂| 福利视频第一区| 欧美精品免费播放| 国模私拍一区二区三区| 日韩精品一区二区视频| 久久久www成人免费精品张筱雨| 久久成人精品一区二区三区| 成人免费在线视频网站| 国产精品一区二区在线| 日韩精品在线视频美女| 日韩电影在线观看中文字幕| 国产一区二区久久精品| 欧美日韩综合视频网址| 欧美视频中文字幕在线| 午夜精品福利在线观看| 成人黄色短视频在线观看| 日韩高清有码在线| 国产精品亚洲网站| 成人羞羞国产免费| 亚洲综合一区二区不卡| 国产一区二区三区四区福利| 久久综合九色九九| 久久久久久久一区二区三区| 日韩国产中文字幕| 久久久国产视频91| 97久久精品视频| 成人性教育视频在线观看| 在线日韩日本国产亚洲| 在线播放国产精品| 国产欧美一区二区三区四区| 亚洲人成免费电影| 国产精品96久久久久久又黄又硬| 久久久久北条麻妃免费看| 国产成人一区二| 91av在线播放视频| 91免费国产视频| 91理论片午午论夜理片久久| 欧美性xxxx极品hd满灌| 亚洲一区精品电影| 亚洲精品美女在线观看| 91成人免费观看网站| 欧美又大又硬又粗bbbbb| 国产丝袜一区二区三区免费视频| 亚洲欧美在线播放| 日韩成人久久久| 精品爽片免费看久久| 91精品久久久久久久| 欧美激情精品久久久久久大尺度| 国产精品美女久久久免费| 成人免费激情视频| 国产精品久久久久aaaa九色| 中文字幕欧美精品日韩中文字幕| 国产精品pans私拍| 亚洲第一精品自拍| 在线观看亚洲视频| 中文字幕亚洲欧美日韩在线不卡| 国产欧美一区二区三区久久人妖| 日韩一区二区三区国产| 亚洲一区二区三区香蕉| 成人免费大片黄在线播放| 欧美电影免费观看电视剧大全| 中文字幕亚洲情99在线| 国产日产欧美a一级在线| 国产精品三级网站| 欧美日韩国产激情| 国产一区二中文字幕在线看| 国产精品高潮在线| 国产精品视频不卡| 欧美日本啪啪无遮挡网站| 高跟丝袜欧美一区| 欧洲亚洲妇女av| 自拍偷拍亚洲欧美| 成人a在线观看| 亚洲国产精品女人久久久| 91久久综合亚洲鲁鲁五月天| 午夜精品久久久久久久久久久久| 性欧美在线看片a免费观看| 亚洲美女精品成人在线视频| 欧美日韩国产精品一区二区三区四区| 成人久久精品视频| 美日韩精品视频免费看| 欧美中文字幕在线观看| 亚洲第一男人av| 国产精品福利在线观看网址| 国产视频综合在线| 成人黄色在线播放| 人人爽久久涩噜噜噜网站| 国产a∨精品一区二区三区不卡| 国产精品入口夜色视频大尺度| 一本色道久久88综合日韩精品| 午夜精品99久久免费| 一区二区日韩精品| 国产视频观看一区| 成人久久久久久久| 91在线观看免费观看| 亚洲国产另类 国产精品国产免费| 永久555www成人免费| 亚洲国产日韩欧美综合久久| 午夜剧场成人观在线视频免费观看| 国产精品亚洲美女av网站| 久久久久成人精品| 亚洲国产精品电影在线观看| 欧美激情视频网址| 在线性视频日韩欧美| 成人午夜两性视频| 欧美日韩另类在线| 欧美中文在线观看| 九九九久久久久久| 久久精品99无色码中文字幕| 亚洲国产日韩欧美在线动漫| 中文字幕亚洲无线码a| 97精品伊人久久久大香线蕉| 日韩av免费在线播放| 国产精品第100页| 91九色国产在线| 欧美黄色免费网站| 国产精品亚洲第一区| 亚洲国产天堂久久综合| 米奇精品一区二区三区在线观看| 国产欧美日韩91| 欧美在线免费观看| 国产成人涩涩涩视频在线观看| 久久精品亚洲94久久精品| 欧美日韩国产色| 中文字幕一区二区三区电影| 久久伊人精品一区二区三区| 欧美高清激情视频| 亚洲一级免费视频| 久久99视频精品| 九九九热精品免费视频观看网站| 日韩激情视频在线| 欧美国产欧美亚洲国产日韩mv天天看完整| 亲子乱一区二区三区电影| 久久中文字幕国产| 亚洲国产精品久久91精品| 欧美一区二区三区精品电影| 欧美激情网友自拍| 久久777国产线看观看精品| 久久不射热爱视频精品| 久久99精品国产99久久6尤物| 欧美野外猛男的大粗鳮| 国产精品丝袜久久久久久不卡| 国内揄拍国内精品少妇国语| 高清欧美性猛交xxxx黑人猛交| 热久久99这里有精品| 久久精品成人动漫| 欧美激情精品久久久久久久变态| 一区二区在线免费视频| 久久久久久久影院| 日韩国产在线看| 国产精品久久久精品| 欧美激情免费视频| 欧美另类在线观看| 中文字幕日韩精品在线| 欧美亚洲视频一区二区| 亚洲国产精品人人爽夜夜爽| 日韩视频亚洲视频| 国产精品久久久一区| 欧美福利在线观看|