性能調優5:執行計劃

来源:https://www.cnblogs.com/ljhdo/archive/2019/01/10/4794216.html
-Advertisement-
Play Games

執行計劃的編譯和生成是很耗費資源和時間的,因此,SQL Server會把生成的任一執行計劃緩存起來,以便重用。 一,緩存機制 SQL Server使用特定的緩存機制,以重用之前已經生成的執行計劃: Ad hoc 查詢緩存 參數化Ad Hoc查詢緩存 sys.sp_executesql 執行的查詢,是 ...


查詢優化器基於當前的統計信息和參數,衡量開銷之後,選擇“最優”的執行計劃,需要註意的是,“最優”是相對的,優化器不可能窮舉所有的執行計劃來評估其開銷,這個“最優”的標準是對當前參數和當前的統計信息來說的,優化器從生成的備選執行計劃中選擇開銷最小的。由於執行計劃的編譯和生成是很耗費資源和時間的,因此,SQL Server會把生成的任一執行計劃緩存起來,以便重用。

由於關係表的數據和結構可能發生改變,數據更新會導致統計信息過時,而之前的參數可能不具有代表性,使得已生成的執行計劃不能代表其他參數值,導致查詢性能低下。因此,應當監控執行計劃的性能,當發現參數嗅探問題時,應該及時修改代碼以重編譯;當發現統計信息過期時,應及時更新統計信息等。

一,緩存機制

SQL Server使用特定的緩存機制,以重用第一次執行查詢時生成的執行計劃,總的來說,SQL Server內部有以下四種執行計劃緩存機制:

  • Ad hoc 查詢緩存
  • 參數化Ad Hoc查詢緩存
  • sys.sp_executesql 執行的查詢,是一種參數化的查詢語句
  • 存儲過程

對於Adhoc查詢的緩存,是SQL Server自動進行的,用戶不能幹預,而後兩種是用戶可以干預的,用戶可以通過優化代碼來複用“模板化”的查詢。所謂模板化語句,是指除了個別的常量發生變化之外,語句主體不變,可以把變化的常量作為一個參數,不變的語句主體作為一個模板來處理,SQL Server優化器把這個模板編譯成執行計劃,傳入不同的參數會使用相同的執行計劃。

1,Ad Hoc查詢緩存

對於任意一個Ad Hoc查詢,SQL Server都會緩存它的執行計劃,但是,只有當批處理語句的文本完全匹配時,才會復用已緩存的執行計劃,完全匹配的處理過程是:

  • SQL Server根據批處理語句的文本計算出一個Hash值,對後續的Ad Hoc查詢的文本同樣計算Hash值,當兩個Hash值相同時,說明兩個批處理的文本完全相同,相當於同一個查詢的重覆執行,SQL Server優化器會復用已緩存的執行計劃。
  • 如果Ad Hoc查詢的文本有任意一個字元發生變化(比如,大寫字元變小寫字元,不同的換行,多了一個空格等),都會導致計算出的Hash值不同,進而不能復用執行計劃。也就是說,Ad Hoc查詢的文本必須完全匹配才能復用執行計劃。

大量的Ad Hoc查詢緩存會占用計劃緩存的空間,這些緩存可能只會被使用一次,以後再也不會被使用。如果資料庫系統中存在大量的一次性查詢語句,應設置Server 級別的性能優化選項:Optimize for Ad hoc Wrokloads。

“針對即席工作負載進行優化”是一個Server級別的性能優化選項,用於提高包含許多臨時批處理的工作負載的計劃緩存的效率,如果把該選項設置為True,則資料庫引擎在首次編譯批處理時只保留計劃緩存中的一個存根,而不是存儲整個執行計劃。當再次調用該批處理時,資料庫引擎識別出該批處理在之前被執行過,進而從計劃緩存中刪除該執行計劃的存根,並把完全編譯的執行計劃添加到計劃緩存中。當非參數化的Ad-Hoc查詢較多時,可以避免計劃緩存存儲過多的不會被覆用的執行計劃。

2,參數化Ad-Hoc

SQL Server 自主決定是否把查詢中的常量作為參數來對待,除了常量不同之外,其他語句主體都相同,這就是這個查詢語句的模板,不同的參數使用相同的執行計劃。

例如,對於以下兩個查詢語句,除了常量1和2不同之外,其他語句都相同,

select ID, Name from dbo.Users where ID=1
select ID, Name from dbo.Users where ID=2

SQL Server對該語句做參數化處理,得到模板,只要語句符合該模板,優化器就復用已緩存的執行計劃。

select ID, Name from dbo.Users where ID=@id

3,Prepared 查詢緩存

用戶使用sys.sp_executesql 控制參數和模板,只要模板相同,而參數不同,都可以復用已緩存的執行計劃。

4,存儲過程

用戶創建的存儲過程,在第一次執行時,編譯和生成執行計劃,並緩存到計劃緩存中,當下次調用相同的存儲過程,即使使傳遞的參數不同,SQL Server都會復用執行計劃。

二,參數嗅探

參數嗅探是指在創建存儲過程,或者參數化查詢的執行計劃時,根據傳入的參數進行預估並生成執行計劃。SQL Server生成的執行計劃對當前參數來說是最優的,而對其他大多數參數來說,是非常低效的。有些時候,針對一個查詢的第一次傳參,已經產生了一個執行計劃,當後續傳參時,由於存在對應參數的數據分佈等問題,導致原有的執行計劃無法高效地響應查詢請求,這就出現參數嗅探問題。

參數嗅探的本質是優化器根據參數來生成的執行計劃不是最優的,導致優化器在復用執行計劃時,語句的查詢性能變得十分低下。對於參數嗅探問題,必須重新生成執行計劃,可以使用語句重編譯,編譯提示(optimize for)等功能來避免。

三,影響執行計劃復用的因素

SQL Server不會永久保存計劃的緩存,並且存在緩存中的執行計劃也不會永久不變,每個計劃都會有一個Age值,當SQL Server探測到記憶體壓力時,會觸發Lazy Writer進程,用於清空所有的臟頁,釋放數據緩存。當掃面到計劃緩存時,會降低Age值,當復用一次計劃時,會增加Age值。當系統遇到記憶體壓力,或Age值降到0時,執行計劃會被移除記憶體。

除了這兩個條件之外,當遇到下麵的條件時,執行計劃一會被移除記憶體,被重新編譯:

  • 查詢引用的基礎表的結構被更改
  • 查詢引用的索引被更改或被刪除
  • 查詢引用的統計信息被更新
  • 執行計劃被強制重新編譯(詳見本問第四小節)
  • 單一查詢中混合了DDL和DML操作,也稱為延遲編譯
  • 在查詢中修改set選項
  • 查詢所用到的臨時表的結構被修改
  • 等等

在執行計劃執行過程中,執行計劃被重新編譯,是優化器根據表結構,索引結構和統計信息做出優化的結構,目的是為了避免繼續使用不合適的執行計劃。

四,強制重新編譯執行計劃

修改存儲過程,觸發器等模塊(Module)能夠使其執行計劃重新編譯,除此之外,還有其他方法,能夠強制重新編譯執行計劃

1,標記,下次重新編譯

使用該存儲過程,標記一個執行模塊(SP,Trigger,User-Defined Function)在下次執行時,重新編譯執行計劃

sys.sp_recompile [ @objname = ] 'object'

2,不復用執行計劃

在創建存儲過程時,使用WITH RECOMPILE 選項,在每次執行SP時,都重新編譯,使用新的執行計劃。

CREATE PROCEDURE dbo.usp_procname 
    @Parameter_Name varchar(30) = 'Parameter_default_value'
WITH RECOMPILE

3,執行時重新編譯

在執行存儲過程時,重新編譯存儲過程的執行計劃

exec dbo.usp_procname @Parameter_name='Parameter_value' 
WITH RECOMPILE

4,語句級別的重新編譯

在SP中,使用查詢選項 option(recompile),只重新編譯該語句級別的執行計劃

select column_name_list
from dbo.tablename
option(recompile)

SQL Server在執行查詢之後,查詢提示(RECOMPILE)指示存儲引擎將計劃緩存拋棄,在下次執行存儲過程時,強制查詢優化器重新編譯,生成新的執行計劃。在重新編譯時,SQL Server 優化器使用當前的變數值生成新的計劃緩存。

五,控制執行計劃

優化器會根據查詢選擇執行計劃,選擇索引,表關聯演算法等,但是,當發現優化器選擇了低效的執行計劃時,可以使用hint來控制執行計劃,SQL Server提供了三種類型的hint:

  • 查詢提示(query hint):告知優化器在整個查詢過程中都應用某個提示,
  • 關聯提示(join hint):告知優化器在關聯時使用特定的關聯演算法
  • 表提示(table hint):告知優化器使用表掃描,還是表上特定的索引

1,查詢提示

使用option來設置查詢提示,

  • 用於group by 聚合,可以控制分組的演算法:hash group 和order group
  • 用於控制關聯的演算法, option(hash join)
  • 通常情況下,優化器決定表關聯的順序,可以使用force order選項,使優化器按照join的順序來關聯, option(force order)
  • 使用maxdop來確定語句執行的最大併發度,option(maxdop 1),取消併發執行。
  • 按照指定的參數來優化 option(optimize for (@para_name= constant_value))

2,關聯提示

在 join關鍵字前面使用Loop,Merge和Hash來控制關聯的演算法

3,表提示

在引用的表名後面,通過with()來設置表提示 table_name with(hints),

當使用索引時,使用 with(index(index_name))來設置,

 

參考文檔:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 功能 顯示目錄文件 ls 選項[-alh] [路徑、文件或目錄】 -l(long) 表示 list,表示以詳細列表的形式進行展示;-h 用“k”“M”"G"來顯示文件的目錄和大小; -a (all)表示顯示所有的文件和文件夾(包含了隱藏文件(一般是以“.”開頭)和文件夾) 1、 #mkdir 路徑 ...
  • 一 etcd發現簡介 1.1 需求背景 在實際環境中,集群成員的ip可能不會提前知道。如使用dhcp自動獲取的情況,在這些情況下,使用自動發現來引導etcdetcd集群,而不是指定靜態配置,這個過程被稱為“發現”。 etcd Discovery 使用已有的 etcd cluster 來註冊和啟動 D ...
  • Vim命令合集 命令歷史 以:和/開頭的命令都有歷史紀錄,可以首先鍵入:或/然後按上下箭頭來選擇某個歷史命令。 啟動vim 在命令行視窗中輸入以下命令即可 vim 直接啟動vim vim filename 打開vim並創建名為filename的文件 文件命令 打開單個文件 vim file 同時打開 ...
  • Linux下一切皆文件 1、root@mk-virtual-machine:/home/mk# root:該位置表示當前終端登錄的用戶名 mk-virtual-machine:/home/mk:當前終端的工作目錄 #:超級管理用戶登錄 $ :普通用戶 2、su或su username :進入超級用戶 ...
  • 一、環境準備 1、最小化安裝centos7.5系統 2、安裝常用軟體包 yum install -y net-tools vim bash-completion 3、關閉selinux和修改主機名 vim /etc/selinux/config SELINUX=disabled vim /etc/h ...
  • 一 etcd集群概述 1.1 概述 靜態啟動etcd集群要求每個成員都知道集群中的另一個成員。Etcd運行在集群的每個coreos節點上,可以保證coreos集群的穩定,可靠的運行。當集群網路出現動蕩,或者當前master節點出現異常時,etcd可以進行master節點的選舉工作,同時恢復集群中損失 ...
  • [TOC] 1. Linux用戶及許可權管理 1.1. who 查看當前誰登錄了我 who q: 一共有多少個人登錄了我 先ping通電腦: 遠程登錄電腦: 查看誰登錄了我的電腦: 1.2. 查看當前用戶: whoami 查看當前系統當前賬號的用戶名 1.3. 添加用戶賬號: useradd | 參數 ...
  • /opt/a.sh ` 之後寫一個定時腳本2分鐘捕捉一次 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...