日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

【SQL进阶】03.执行计划之旅1 - 初探

發布時間:2025/3/19 数据库 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SQL进阶】03.执行计划之旅1 - 初探 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

聽到大牛們說執行計劃,總是很惶恐,是對知識的缺乏的惶恐,所以必須得學習執行計劃,以減少對這一塊知識的惶恐,下面是對執行計劃的第一講-理解執行計劃。

本系列【T-SQL】主要是針對T-SQL的總結。

SQL基礎

【T-SQL基礎】01.單表查詢-幾道sql查詢題

【T-SQL基礎】02.聯接查詢

【T-SQL基礎】03.子查詢

【T-SQL基礎】04.表表達式-上篇

【T-SQL基礎】04.表表達式-下篇

【T-SQL基礎】05.集合運算

【T-SQL基礎】06.透視、逆透視、分組集

【T-SQL基礎】07.數據修改

【T-SQL基礎】08.30分鐘全面解析-SQL事務+隔離級別+阻塞+死鎖(推薦 +165)

【T-SQL基礎】09.可編程對象

SQL進階

【SQL進階】01.好用的SQL TVP~~獨家贈送[增-刪-改-查]的例子

【SQL進階】02.理解SQL查詢的底層原理(推薦 +5)

【SQL進階】03.執行計劃之旅1 - 初探?(最新)

SQL性能調優

【SQL性能調優】01.TempDB的使用和性能問題

?

持續更新......歡迎關注我!

?

?

一、為什么需要執行計劃?

(1)幫助分析

當我們想要去分析SQL語句存在很慢時,需要有一個分析工具幫助我們分析SQL語句中哪些地方存在性能問題,而這個分析工具就是執行計劃,看懂執行計劃就能知道哪些地方有性能問題,然后結合自己已有的SQL知識分析為什么這些地方有性能問題,進而嘗試提出解決方案,并測試自己的方案是否能提高性能,以及方案是否合理。

(2)獲取其他信息

? ? ? ?a.哪些索引被用在查詢中

? ? ? ?b.數據是怎樣關聯起來的

? ? ? ?c.數據是怎樣檢索的

? ? ? ?d.為什么SQL Server沒有使用這些索引

? ? ? ?e.SQL語句的執行順序

二、什么是執行計劃?

SQL語句執行之前,需要有一個執行的方案,而這個方案是由查詢優化器(查詢分析器)產生的,并且是高效的、開銷最小的方案,這就是執行計劃。不知道查詢優化器的可以看我寫之前寫的一篇博客:

【T-SQL進階】02.理解SQL查詢的底層原理

三、如何顯示執行計劃?

執行計劃有三種格式:圖形化執行計劃,文本化執行計劃,XML格式的執行計劃。

(1)圖形化執行計劃

?

優點:可視性好。

a.估計的執行計劃

可以通過鼠標點擊圖標顯示估計的執行計劃或者通過快捷鍵Ctrl+L顯示估計執行計劃。預估執行計劃不會真正執行,只是預估出來的執行計劃。

b.實際的執行計劃

單擊實際的執行計劃圖標,該圖標處于選中狀態,然后執行SQL語句,將會顯示實際執行的執行計劃。

(2)文本化執行計劃

?

?

用獨立的行來代表每一個迭代器。使用豎線(符號“|”)來代表查詢樹中迭代器之間的父子關系。數據都是從子迭代器流向父迭代器。

優點:和圖形計劃比較,文本執行計劃更容易保存、處理、搜索和比較。

--顯示完整的預估執行計劃信息 SET SHOWPLAN_TEXT ON GO --顯示預估執行計劃的有限信息,可以用osql.exe等工具分析 SET SHOWPLAN_ALL ON GO --顯示完整的實際執行計劃信息 SET STATISTICS PROFILE ON GO

總結:

?

(3)XML執行計劃

優點:三種執行計劃中最詳細的。圖形執行計劃可以保存為擴展名為.sqlplan的XML格式的計劃文件,打開此文件將會以圖形化的執行計劃展示。

?

--顯示預估執行計劃 SET SHOWPLAN_XML ON GO --顯示實際計劃的XML格式數據 SET STATISTICS XML ON GO

?總結

四、如何分析執行計劃?

下面分析三種情況的執行計劃:

1.堆表

2.聚集索引

3.非聚集索引

結構掃描查找書簽查找
堆表表掃描沒有這種情況RID 查找
聚集索引聚集索引掃描聚集索引查找沒有這種情況
非聚集索引如果用到了索引,則是索引掃描索引查找Key 查找

?

?

?

?

關于表掃描的那些事:

  • 沒有索引的表稱作堆表,查找匹配行用的是表掃描。
  • 如果出現表掃描操作,則證明這個表上一定沒有聚集索引。

關于索引查找的那些事:

假設[列1]上有一個單列索引,可以使用這個索引查找下面這些謂詞:

? 1.[列1] = 1.23

? 2.[列1] > 1.23

? 3.[列1] BETWEEN 1 AND 100

? 4.[列1] LIKE 'abc%'

? 5.[列1] IN (1,3,7,10)

? 不能使用這個索引對下列這些謂詞進行查找:

? 1.ABS[列1] = 1

? 2.[列1] + 10 > 12

? 3.[列1] LIKE '%abc'

關于非聚集索引的那些事:

  • 如果只有非聚集索引時,非聚集索引不包含查詢列時,則SQL查詢優化器選擇非聚集索引掃描。
  • 只有非聚集索引時,非聚集索引不包含過濾條件列時,則選擇表掃描。
  • 非聚集索引具有獨立于數據行的結構。 非聚集索引包含非聚集索引鍵值,并且每個鍵值項都有指向包含該鍵值的數據行的指針。
  • 從非聚集索引中的索引行指向數據行的指針稱為行定位器。 行定位器的結構取決于數據頁是存儲在堆中還是聚集表中。 對于堆,行定位器是指向行的指針。 對于聚集表,行定位器是聚集索引鍵。
  • 您可以向非聚集索引的葉級添加非鍵列(包含列)以跳過現有的索引鍵限制(900 字節和 16 鍵列),并執行完整范圍內的索引查詢。
  • 關于聚集索引的那些事:

    1. 如果表上有聚集索引,則掃描稱作聚集索引掃描,查找稱作聚集索引查找;

    2. 聚集索引掃描和表掃描的性能沒多大差異;

    3.聚集索引根據數據行的鍵值在表或視圖中排序和存儲這些數據行。

    4.索引定義中包含聚集索引列。

    5.每個表只能有一個聚集索引,因為數據行本身只能按一個順序排序。

    6.只有當表包含聚集索引時,表中的數據行才按排序順序存儲。 如果表具有聚集索引,則該表稱為聚集表。如果表沒有聚集索引,則其數據行存儲在一個稱為堆的無序結構中。

    7.加了聚集索引不一定能提高性能,有些情況下,性能可能不如表掃描;

    8.聚集索引就是表本身。表有多少行和多少列,聚集索引就有多少行和和多少列。

    9.單表查詢中,過濾條件中有聚集索引列,且能用這個索引查找過濾條件中的謂詞,則是聚集索引查找,過濾條件中沒有聚集索引列則是聚集索引掃描。

    (1)沒有索引的情況

    創建myOrder表

    USE [Test] GOCREATE TABLE [dbo].[myOrder]([id] [int] NOT NULL,[customer] [nvarchar](100) NOT NULL ) ON [PRIMARY]GO

    myOrder只有兩列id,customer,這兩列上面都沒有索引。

    SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'

    下面是執行計劃:

    ?

    customer列上面沒有索引,SQL Server需要讀取myOrder表的每一行來判斷customer='ddd',如果結果為true,則返回此行。

    查詢的示例圖如下,customer=ddd 存在三條記錄。

    注意:

    1.掃描及查找是SQL Server用來從表和索引中讀取數據的迭代器;

    2.掃描用來處理整個表或索引的全部分支;

    3.查找是在謂詞基礎上有效返回索引中一個或多個范圍中的行。

    ?

    (2)有非聚集索引的情況

    在id上創建非聚集索引

    USE [Test] GO--刪除索引dbo.myOrder.ID_NON_INDEX DROP INDEX dbo.myOrder.ID_NON_INDEXCREATE NONCLUSTERED INDEX [ID_NON_INDEX] ON [dbo].[myOrder] ([id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] GO

    1.查詢條件的列上沒有非聚集索引,查詢列上沒有非聚集索引->表掃描

    --id列上有索引,customer列上沒有索引,查詢條件中用的是customer='ddd'進行過濾。 --由于customer列上沒有索引,所以需要進行表掃描來找到符合customer='ddd'的行。 SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'SELECT [customer]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [id] = 2 AND [customer] ='ddd'SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2 AND [customer] ='ddd'

    ?

    2.查詢條件的列上有非聚集索引,查詢列上沒有非聚集索引->表掃描

    --id列上有索引,customer列上沒有索引,查詢條件中用的是id=2進行過濾。 --SELECT查詢需要返回customer列,由于customer列上沒有索引,且索引[ID_NON_INDEX]不包含customer列, --即使用非聚集索引掃描找到了符合過濾條件id=2的索引分支,但是只能在該索引分支上面拿到id列的值,因為該索引分支只包含了id列,其他列的值拿不到。 --所以還是需要進行表掃描來找到符合條件的行,然后獲取該行的customer列的值。 --這里有個疑問:為什么找到索引分支后,不能繼續找到對應的行,然后拿到這行的customer列?? SELECT [customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2

    ?

    3.查詢條件的列上有非聚集索引,查詢列上有非聚集索引->索引查找

    --id列上有索引,customer列上沒有索引,查詢條件中用的是id=2進行過濾。 --SELECT查詢需要返回id列,使用非聚集索引掃描找到了符合過濾條件id=2的索引分支,在找到的索引分支上拿到id列的值。 SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [id] = 2

    ?

    3)有聚集索引的情況

    1.查詢條件的列上沒有聚集索引->聚集索引掃描

    -- --id列上有聚集索引,customer列上沒有索引,查詢條件中用的是customer='ddd'進行過濾。 --由于customer列上沒有索引,所以需要進行掃描來找到符合customer='ddd'的行。 --只要有聚集索引,則掃描就是聚集索引掃描。聚集索引和表掃描的性能基本上一樣。 SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'SELECT [customer]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [customer] = 'ddd'

      

    2.查詢條件的列上有聚集索引->聚集索引查找

    --id列上有索引,customer列上沒有索引,查詢條件中用的是id=2進行過濾。 --用聚集索引查找到了id=2的行,由于表中的行就是按照id列來排序的,所以找到了這一行, --也就能找到這一行的所有列,所以能夠拿到customer列。所以是聚集索引掃描。SELECT [customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [id] = 2SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2

      

    3.查詢條件中,有一列有聚集索引,另一列沒有聚集索引->聚集索引查找

    --id列上有索引,customer列上沒有索引,查詢條件中用的是[id] = 2,[customer] ='ddd'進行過濾。 --當過濾條件中有一個可以根據聚集索引來查找時,先用聚集索引來找到匹配的行([id] = 2),然后再在過濾出來的行中篩選處符合[customer] ='ddd'的行。 --所以是聚集索引查找。 --疑問:為什么第二步篩選操作在執行計劃圖中沒有體現??這個地方我想到的是拿到id=2的匹配行后,直接舍棄掉不符合條件[customer] ='ddd'的行,這個舍棄動作就沒有直接體現出來。SELECT [id]FROM [Test].[dbo].[myOrder]WHERE [id] = 2 AND [customer] ='ddd'SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [id] = 2 AND [customer] ='ddd'SELECT [id],[customer]FROM [Test].[dbo].[myOrder]WHERE [customer] ='3333' AND [id] = 2

      

    ?

    ->>【T-SQL】系列文章全文目錄(2017-06-26更新)

    ?


    作  者: Jackson0714
    出  處:http://www.cnblogs.com/jackson0714/
    關于作者:專注于微軟平臺的項目開發。如有問題或建議,請多多賜教!
    版權聲明:本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。
    特此聲明:所有評論和私信都會在第一時間回復。也歡迎園子的大大們指正錯誤,共同進步?;蛘咧苯铀叫盼?
    聲援博主:如果您覺得文章對您有幫助,可以點擊文章右下角【推薦】一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!

    ?

    轉載于:https://www.cnblogs.com/jackson0714/p/SQL_ExecutePlan1.html

    總結

    以上是生活随笔為你收集整理的【SQL进阶】03.执行计划之旅1 - 初探的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。