<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    關于sql的執行計劃(推薦詳細)

    剛開始用SQL Server的時候,我沒有用顯示執行計劃來對查詢進行分析。我曾經一直認為我遞交的SQL查詢都是最優的,而忽略了查詢性能究竟如何,從而對“執行計劃”重視不夠。在我職業初期,我只要能獲取數據就很開心,而不去考慮數據是如何返回的,“執行計劃”對我的查詢作了什么工作。我以為SQL Server會自己去處理查詢的性能問題的。作為一個剛進入IT行業或者剛學到新技術的軟件工程師,在編寫代碼前不太可能有時間去學習其實必須掌握的知識。也許這是因為IT行業競爭太激烈的緣故。

    隨著時間的流逝,數據庫容量慢慢變大了。終于某天,客戶對應用系統的查詢性能感到不滿意了。他面帶怒容來找我,抱怨由于查詢太慢,使得他需要花更多的時間來處理公務。最初,我建議客戶升級其系統資源,例如作為臨時解決方案,增加硬盤容量。雖然硬盤價格現在很便宜了,但是客戶還是要求我提供一個永久性的解決方案,檢查和好好調試查詢語句,來替代那種無休止地升級資源的臨時方案。因為客戶的滿意度對IT行業來說是十分重要的,因此我不得不考慮他的個人建議。我答應他一定會檢查和調整我的代碼。


    如何入手呢?

    在剛進入IT行業時,我知道SQL Server的基礎只是。說實話,向客戶承諾檢查系統的時候,我還沒有一點入手的頭緒。不過我相信我可以通過GOOGL和BOL來獲取相應的信息。

    我閱讀了一些關于SQL Server的書籍,BOL,以及在網上搜索的信息。于是我知道了“顯示執行計劃”的概念。可以在查詢管理器中將該選項的開關設置為ON。“顯示執行計劃”是一個圖形化工具,可以幫助開發者和DBA分析,優化查詢,從而改善性能。

    “顯示執行計劃”中不同的任務具有不同的圖標。本文中我主要對“Table Scan”、“Index Scan”、“Index Seek”、“Cluster Index Scan”以及“Clustered Index Seek”感興趣。也許在以后,可以對別的任務進行另外介紹。

    時間以F1方程式的速度開始流逝,我覺得該是我全面理解“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”、和“Clustered Index Seek”如何工作的時候了。

    我準備開始分析并優化我的查詢。在分析之前,我想到了一些問題。

    • MS-SQL Server什么時候使用"Table Scan"?
    • MS-SQL Server什么時候使用"Index Scan"?
    • MS-SQL Server什么時候使用"Index Seek"?
    • MS-SQL Server什么時候使用"Clustered Index Scan"?
    • MS-SQL Server什么時候使用"Clustered Index Seek"?

    ?

    我主要關注SQL Server是根據什么來使用“執行計劃”分析查詢的。在經過一段時間學習后,我了解了一些相關知識。這些知識應該對開發和DBA新手有幫助。于是我決定寫這篇文章,共享我的知識以幫助別人來理解“執行計劃”。

    如果你喜歡,可以慢慢讀完,也可以在SQL Server上,模擬我下面做的實驗。


    開始入手

    為了解釋“顯示執行計劃”中的“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”,先創建新表,并添加一些示例數據進去。下面是創建新表的腳本:

    ?

    Create Table PerformanceIssue
    (
    ????PRID UniqueIdentifier NOT NULL,
    ????PRCode Int NOT NULL,
    ????PRDesc Varchar (100) NOT NULL
    )
    ON [PRIMARY]

    ?

    表創建后需要添加一些數據。使用下面的腳本添加100,000條記錄進去。腳本執行時間可能比較長,請耐心等待其執行完畢。

    ?

    Declare @Loop Int
    Declare @PRID UniqueIdentifier
    Declare @ PRDesc Varchar (100)

    Set @Loop = 1
    Set @ PRDesc = ''

    WHILE @Loop <= 100000
    BEGIN
    ?? Set @PRID = NewID()
    ?? Set @PRDesc = ' PerformanceIssue - ' + Convert( Varchar(10),@Loop )
    ?? Insert Into PerformanceIssue Values (@PRID, @Loop, @PRDesc)
    ?? Set @Loop = @Loop + 1
    END

    ?

    腳本成功執行后,數據就添加進去了。

    用下面語句來看一下表的內容:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    GO

    ?

    由于記錄較長,因此這里就不列出查詢結果了。

    正如我前面講到,我想解釋何時會有“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”。上述哪個會改善性能呢?

    當SQL Server返回數據時,我們想知道SQL Server采取何種掃描機制來協助獲取數據。首先看一下“Table Scan”。我們想了解什么時候“Table Scan”會產生。

    選擇“顯示執行計劃”或者使用熱鍵“Alt + Q”來激活“顯示執行計劃”,當然也可以用快捷鍵“Ctrl+K”。

    看一下執行下面查詢后的“執行計劃”結果。

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    GO


    上面的“執行計劃”中,SQL Server用到了“Table Scan”。我問自己為什么會有“Table Scan”,SQL Server是根據什么來使用該方法的。難道是因為我想獲取所有100,000條記錄嗎?于是我換了一個角度進行思考,如果來避免查詢中出現“Table Scan”呢?此時我對SQL Server的掃描機制還不是很清楚,那么該如何優化查詢呢?下面的SELECT查詢中僅選擇兩列:[PRID, PRCode]。

    ?

    Select PRID, PRCode
    From PerformanceIssue
    GO


    查詢執行后,執行計劃和第一個查詢一樣。于是將查詢改變為只檢索一個字段 [PRID]。

    ?

    Select PRID
    From PerformanceIssue

    GO


    查詢執行后,執行計劃仍然和第一個查詢的相同。對“Estimated row size”屬性不需要太大關注。意思我立刻決定只獲取一條記錄,看看執行計劃會如何。查詢語句如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'
    -- PRID GUID value might be differ in your machine

    GO

    ?

    執行完成后,執行計劃顯示:

    查詢仍然使用了“Table Scan”方法來顯示數據。

    那么,我需要想其它辦法來避免“Table Scan”。首先我想到應該給表加上索引。于是我在PRID字段上創建非聚集索引。添加了索引后是否就能避免“Table Scan”?下面我們開始討論關于“Index Scan”和“Index Seek”的主題。


    Index Scan 和 Index Seek

    首先在PRID字段上創建非聚集索引。

    ?

    CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID
    ON PerformanceIssue (PRID)
    GO

    ?

    本文假定讀者已經知道非聚集索引如何工作的知識。了解非聚集索引更詳細的信息,請閱讀BOL相關主題,也可參看 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我們詳細講述“Index Scan”是如何工作的。

    執行下面語句并查看執行計劃的結果。

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    GO


    奇怪了,“Table Scan”仍然用到了。為什么SQL Server沒有用到那個非聚集索引?于是繼續優化查詢語句,選擇檢索兩個字段 [PRID, PRCode] 。

    ?

    Select PRID, PRCode From PerformanceIssue
    GO


    執行結果是和上一個查詢結果一摸一樣。于是修改查詢為只檢索一個字段 [PRID] 。

    ?

    Select PRID
    From PerformanceIssue
    GO

    ?

    執行計劃結果如下:

    “Index Scan”在查詢中被用到了,這很好。很自然,接下來的問題就是“Index Scan”什么時候會被用到。字段PRID上有一個索引,查詢語句中選中的字段為PRID。執行查詢的時候,SQL Server掃描索引頁,因此用到了“Index Scan”方法。前面的查詢中選擇了有索引的和沒有索引的字段,SQL Server無法使用“Index Scan”。當查詢中只選擇有索引的字段時,SQL Server就使用了“Index Scan”。我不清楚SQL Server底層到底是如何判斷的,不過通過這些試驗,我認為當查詢中只選擇有索引的字段時,SQL Server就使用“Index Scan”方法

    下面看“Index Seek”方法何時產生。當我看到“Seek”這個詞時,第一反應就是條件查詢這個主意。

    我嘗試三種不同的帶WHERE語法的查詢語句,以找出那種會用“Index Seek”。第一種語句如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRCode = 8
    GO

    ?

    結果顯示,執行計劃使用了“Table Scan”。

    第二種語句如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRDesc = ' PerformanceIssue - 8'
    GO

    ?

    執行計劃仍然使用“Table Scan”方法。

    第三種查詢語句如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'

    -- PRID GUID value might be differ in your machine
    GO



    查詢用到了“Index Seek”和“Bookmark Lookup”方法。用到“Index Seek”是因為WHERE后面使用帶索引的字段PRID來進行過濾。“Bookmark Lookup”方法被用到是因為查詢中選擇了沒有索引的字段。如果去掉這兩個沒有索引的字段,那么“Bookmark Lookup”方法就可以去掉。當然如果只返回PRID字段,那么該查詢就沒什么意義了,因為WHERE語句后面已經給出PRID具體取值了。

    我認為“Index Seek”在性能改善上比“Index Scan”和“Table Scan”要好,這主要表現在下面幾個方面:

    ?

    1. “Index Seek”不需要對表和索引頁進行掃描;而“Table Scan”和“Index Scan”需要。
    2. “Index Seek”利用“WHERE”來過濾獲取的數據,這樣比用“Index Scan”和“Table Scan”快很多。

    ?

    當我完成這些測試后,我同事問我一個很有意思的問題:SQL Server什么時候使用“Clustered Index Scan”和“Clustered Index Seek”?下面對“Clustered Index Scan”和“Clustered Index Seek”進行實驗。

    我決定在PRCode上建一個聚集索引來測試“Clustered Index Scan”和“Clustered Index Seek”。


    Clustered Index Scan & Clustered Index Seek

    下面的腳本刪除PRID字段上的索引,并在PRCode字段上創建聚集索引。

    ?

    Drop Index PerformanceIssue.UNC_PRID
    GO
    CREATE UNIQUE CLUSTERED INDEX UC_PRCode
    ON PerformanceIssue( PRCode)
    GO
    -------------
    Clustered index has been created successfully.
    Index has been created.

    ?

    關于聚集索引的基礎知識請查閱聯機幫助的相關主題或者 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我們將重點放在“Clustered Index Scan”和“Clustered Index Seek”如何被使用上。

    執行下面查詢語句:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    GO

    ?

    查詢執行后,可以看到執行計劃中用到了“Clustered Index Scan”。

    下面用三種不同的WHERE方式來試驗何時SQL Server會用到“Clustered Index Seek”。第一種形式如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRDesc = ' PerformanceIssue - 8'
    GO

    ?

    查詢執行后,可以看到執行計劃中用到了“Clustered Index Scan”。

    第二種形式如下:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'

    -- PRID GUID value might be differ in your machine
    GO

    ?

    查詢執行后,發現執行計劃中用到的仍然是“Clustered Index Scan”。

    第三種形式:

    ?

    Select PRID, PRCode, PRDesc
    From PerformanceIssue
    Where PRCode = 8
    GO

    ?

    這次執行計劃用到了“Clustered Index Seek”。

    當在WHERE后用到PRCode字段的時候,“Clustered Index Seek”被用到。執行計劃對聚集索引表檢索的時候,因為在選取的字段中,包括沒有索引的字段,所以不用用到“Bookmark Lookup”方法。

    我個人認為,從改善性能角度考慮,“Clustered Index Seek”比“Clustered Index Scan”和“Index Seek”要好。

    ?

    1. “Clustered Index Seek”不需要掃描整個聚集索引頁。
    2. 和“Index Scan”相比,對于檢索選擇的字段包含那些沒有索引的字段時,“Clustered Index Seek”不會有“Bookmark Lookup”方法出現。

    ?

    通過這些試驗,我對執行計劃的應用積累了實際經驗。我知道哪種掃描機制可以提高性能,從而是的客戶滿意。

    ?

    posted on 2008-04-08 23:38 金家寶 閱讀(20340) 評論(8)  編輯  收藏 所屬分類: MS-SQL

    評論

    # re: 關于sql的執行計劃(推薦詳細)[未登錄] 2012-10-16 16:51 candy

    “因為在選取的字段中,包括沒有索引的字段,所以不用用到“Bookmark Lookup”方法” 這句話是錯的

    因為在有聚集索引的表中根據聚集索引檢索數據,索引中已經包含了該條數據的全部內容,所以才不需要Bookmark Lookup  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細) 2013-01-22 17:05 張俊

    好東東  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細)[未登錄] 2013-05-15 18:08 Frank

    很少看到寫得這么細致的文章,掌聲鼓勵!  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細) 2013-07-22 15:36 很郁悶

    什么是BOL?是BLOG嗎?  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細) 2014-04-03 16:28 niaomingjian

    @candy
    有道理  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細) 2015-03-21 14:22 王振

    @niaomingjian
    說的很好  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細)[未登錄] 2015-04-13 17:39 lee

    2.“Index Seek”利用“WHERE”來過濾獲取的數據,這樣比用“Index Scan”和“Table Scan”快很多。 個人覺得這句話表達意思不對,不建立索引的時候,也可以用WHERE來過濾獲取數據。  回復  更多評論   

    # re: 關于sql的執行計劃(推薦詳細)[未登錄] 2015-06-18 15:17 A

    內容(請不要發表任何與政治相關的內容)   回復  更多評論   

    主站蜘蛛池模板: a级在线观看免费| 国产成人亚洲合集青青草原精品| 羞羞视频免费网站含羞草| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 任你躁在线精品免费| 亚洲人成亚洲精品| 久久WWW色情成人免费观看| 韩国亚洲伊人久久综合影院| 亚洲午夜久久久影院| 在线免费观看一级毛片| 中文毛片无遮挡高清免费| 亚洲一区二区三区高清视频| 日本二区免费一片黄2019| 亚洲乱色熟女一区二区三区蜜臀| 午夜宅男在线永久免费观看网| 亚洲另类精品xxxx人妖| 免费无码又爽又刺激聊天APP| 亚洲国产精品成人午夜在线观看 | 国产精品观看在线亚洲人成网| 国产精品高清全国免费观看| 免费国产高清毛不卡片基地| 亚洲人成无码网站| 日本一区二区三区免费高清 | 春意影院午夜爽爽爽免费| 亚洲AV日韩AV永久无码绿巨人 | 国产成人精品日本亚洲11| 亚洲国产精品一区二区三区久久| 日韩免费高清播放器| 亚洲黄色激情视频| 亚洲精品无码国产| 夜夜嘿视频免费看| 你懂得的在线观看免费视频| 亚洲欧洲精品成人久久曰| 亚洲熟妇av一区二区三区| 天天影院成人免费观看| 国产V片在线播放免费无码| 亚洲影视自拍揄拍愉拍| 国产亚洲精AA在线观看SEE| 免费观看男人免费桶女人视频| av永久免费网站在线观看| 黄色网址免费在线|