SQL Server OPTION (OPTIMIZE FOR UNKNOWN) 測試總結

来源:https://www.cnblogs.com/kerrycode/archive/2018/09/21/9684192.html
-Advertisement-
Play Games

關於SQL Server的查詢提示OPTION (OPTIMIZE FOR UNKNOWN) ,它是解決參數嗅探的方法之一。 而且對應的SQL語句會緩存,不用每次都重編譯。關鍵在於它的執行計劃的準確度問題, 最近在優化的時候,和同事對於這個查詢提示(Query Hint)有一點分歧,遂動手實驗驗證、... ...


 

關於SQL Server的查詢提示OPTION (OPTIMIZE FOR UNKNOWN) ,它是解決參數嗅探的方法之一。 而且對應的SQL語句會緩存,不用每次都重編譯。關鍵在於它的執行計劃的準確度問題, 最近在優化的時候,和同事對於這個查詢提示(Query Hint)有一點分歧,遂動手實驗驗證、總結了一些東西。

 

關於提示OPTION (OPTIMIZE FOR UNKNOWN),它會利用統計數據和標準演算法生成一個折中、穩定的執行計劃,但是它是無法利用直方圖(histogram)信息來生成執行計劃。官方文檔的介紹如下:

 

OPTIMIZE FOR 編譯和優化查詢時提示查詢優化器對本地變數使用特定值。僅在查詢優化期間使用該值,在查詢執行期間不使用該值。

 

UNKNOWN

指定查詢優化器在查詢優化期間使用統計數據而不是初始值來確定局部變數的值。OPTIMIZE FOR 可以抵消優化器的預設參數檢測行為,也可在創建計劃指南時使用

 

OPTIMIZE FOR UNKNOWN

指示查詢優化器在查詢已經過編譯和優化時為所有局部變數使用統計數據而不是初始值,包括使用強制參數化創建的參數。有關強制參數化的詳細信息,請參閱強制參數化

如果在同一查詢提示中使用 OPTIMIZE FOR @variable\_name = literal_constant OPTIMIZE FOR UNKNOWN,則查詢優化器將對特定的值使用指定的 literal_constant,而對其餘變數使用 UNKNOWN。這些值僅用於查詢優化期間,而不會用於查詢執行期間

 

OPTIMIZE FOR UNKNOWN是否會用直方圖數據呢? 不會,OPTIMIZE FOR UNKNOWN只會用簡單的統計數據。我們以how-optimize-for-unknown-works這篇博客中的例子來演示一下, 下麵測試環境為SQL Server 2014,資料庫為AdventureWorks2014

 

CREATE PROCEDURE test (@pid int)
AS
SELECT * FROM [Sales].[SalesOrderDetail]
WHERE ProductID = @pid OPTION (OPTIMIZE FOR UNKNOWN);

 

 

為了消除統計信息不准確會幹擾測試結果,我們手工更新一下統計信息。

 

UPDATE STATISTICS [Sales].[SalesOrderDetail] WITH FULLSCAN;

 

 

我們在SSMS裡面點擊包含實際執行計劃選項,然後測試執行該存儲過程,如下截圖所示: 執行計劃居然走聚集索引掃描

 

EXEC test @pid=709

 

clip_image001

 

 

Filter裡面過濾的記錄為456.079,而實際上ProductID=709的記錄有188條,那麼優化器是怎麼估計判斷記錄數為456.709的呢?

 

clip_image002

 

clip_image003

 

 

其實優化器是這樣來估計的:它使用ProductID列的密度(Density)* Rows來計算的

 

SELECT 0.003759399 *121317 ~= 456.079008483 ~= 456.079

 

ProductID列的密度(Density)的計算是這樣來的:

 

ProductID的值有266個,可以用下麵SQL獲取ProductID的值個數

 

 

SELECT COUNT(DISTINCT ProductID) FROM  Sales.SalesOrderDetail

 

SELECT 1.0/266  ~=  0.003759

 

 

然後你可以使用任意不同的參數測試,例如707712......, 你會發現使用查詢提示OPTION (OPTIMIZE FOR UNKNOWN)後,優化器會總是使用相同的執行計劃。也就是說這個查詢提示生成的執行計劃是一個折中的執行計劃 ,對於數據分佈傾斜的比較厲害(數據分佈極度不均衡)的情況下,是極度不建議使用查詢提示OPTION (OPTIMIZE FOR UNKNOWN)的。

 

本人曾經一度對使用OPTIONRECOMPILE)還是OPTION (OPTIMIZE FOR UNKNOWN)感到困惑和極度難以取捨,後面總結了一下:

 

1:執行不頻繁的存儲過程,使用OPTIONRECOMPILE)要優先與OPTION (OPTIMIZE FOR UNKNOWN)

 

2:執行頻繁的存儲過程,使用OPTION (OPTIMIZE FOR UNKNOWN)要優先於OPTIONRECOMPILE

 

3:數據分佈傾斜的厲害的情況下,優先使用OPTIONRECOMPILE

 

    4: 使用OPTION (OPTIMIZE FOR UNKNOWN)會生成一個穩定、統一的執行計劃,如果這個執行計劃的效率基本能滿足用戶需求,那麼優先使用OPTION (OPTIMIZE FOR UNKNOWN)

 

 

 

 

 

參考資料:

 

https://docs.microsoft.com/zh-cn/previous-versions/sql/sql-server-2008/ms181714(v=sql.100)

http://www.benjaminnevarez.com/2010/06/how-optimize-for-unknown-works/

https://blogs.msdn.microsoft.com/sqlprogrammability/2008/11/26/optimize-for-unknown-a-little-known-sql-server-2008-feature/


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

-Advertisement-
Play Games
更多相關文章
  • 1、常用的RPM軟體包命令 安裝軟體的命令格式  rpm –ivh filename.rpm 升級軟體的命令格式  rpm –Uvh filename.rpm 卸載軟體的命令格式  rpm –e filename.rpm 查詢軟體描述信息的命令格式  rpm ...
  • SMB(Server Message Block)協議,服務消息塊協議。 最開始是用於微軟的一種消息傳輸協議,因為頗受歡迎,現在已經成為跨平臺的一種消息傳輸協議。 同時也是微軟歷史上出現安全問題最多的協議。 它的實現複雜,並且預設在所有windows上開放。 SMB常用的埠有兩個139和445,較 ...
  • 使用的是itop4412開發板(僅記錄個人的學習回顧,如有不當之處歡迎指出) 致謝 準備:busybox軟體、uboot(一般和開發板配套)、zImage(kernel內核)、ramdisk uboot.img(系統掛載硬碟使用)、system.img(製作的系統鏡像) system.img的製作步 ...
  • 首先,我在網上看了很久 我先是安裝Python版本SSR,甚至修改源碼 然而運行sslocal -c xxx總是沒有反應 這種方式我試了很多次,發現在Kali機器上使不通 後來又換了橋接模式,也是使不通 最後,我卻發現一個簡單的方法: 直接使用ProxyChains連接我本機的1080埠: Kal ...
  • 今天在查看 /dev/fuse 文件的屬性的時候,看到了crw_ 許可權位,一時反應不過來: 在這裡進行備註一下,相關答案來源於網路。 保持更新,轉載請註明出處。 ...
  • 1.移除舊版本git [root@Git ~]# git --version ## 查看自帶的版本git version 1.8.3.1 [root@Git ~]# yum remove git ## 移除原來的版本 2.安裝所需軟體包 [root@Git ~]# yum install curl- ...
  • 1. 前往ORACLE官網下載最新版本的Java JDK:http://www.oracle.com/technetwork/java/javase/downloads/index.html,預設下載到Downloads文件夾。 2. 在合適的路徑下創建文件夾用來存儲Java JDK,本例選擇在/o ...
  • 1.數據導出exp、expbd和imp、impbd 區別: exp,imp:既可以在客戶端執行也可以在服務端執行,效率慢於expbd、impbd expbd、impbd:只能夠在服務端執行,impbd只能導入expbd導出的文件,impbd不可以 2.不論你用DOS視窗也好,PLSQL工具也好,最終 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...