SQL Server 執行計劃利用統計信息對數據行的預估原理二(為什麼複合索引列順序會影響到執行計劃對數據行的預估)

来源:http://www.cnblogs.com/wy123/archive/2016/10/28/6008477.html
-Advertisement-
Play Games

本文出處:http://www.cnblogs.com/wy123/p/6008477.html 關於統計信息對數據行數做預估,之前寫過對非相關列(單獨或者單獨的索引列)進行預估時候的演算法,參考這裡。 今天來寫一下統計信息對於複合索引在預估時候的計算方法和潛在問題。 本文原形來自於是個實際業務問題, ...


 

本文出處:http://www.cnblogs.com/wy123/p/6008477.html 

  關於統計信息對數據行數做預估,之前寫過對非相關列(單獨或者單獨的索引列)進行預估時候的演算法,參考這裡
  今天來寫一下統計信息對於複合索引在預估時候的計算方法和潛在問題。
  本文原形來自於是個實際業務問題,某SQL在利用一個符合索引做查詢的時候,發現始終會出現預估誤差較大的情況,
  而改變複合索引的列順序,這個預估行數的誤差會發生變化,究其原因在哪裡呢?

  

  先造一個測試環境:

CREATE TABLE TestStatistics
(
    COL1 INT IDENTITY(1,1)  ,
    COL2 INT                ,
    COL3 DATETIME           ,
    COL4 VARCHAR(50)            
)
GO

INSERT INTO TestStatistics VALUES (RAND()*10,CAST(GETDATE()-RAND()*300 AS date),NEWID())
GO 1000000

 

 問題重現

首先看一個非常有意思的問題,
在同一張表上,
先這麼建一個索引:CREATE INDEX IDX_COL2_COL3 ON TestStatistics(COL2,COL3)
執行一個查詢,預估為4127.86
然後DROP掉上面的索引,繼續創建一個索引:CREATE INDEX IDX_COL3_COL2 ON TestStatistics(COL3,COL2)
註意COL2和COL3的順序不一致
繼續執行上面的查詢(查詢條件不變,數據不變,僅僅是索引列順序發生了變化),這一次預估為2414.91

 

查詢條件一樣,數據也一樣,為什麼改變複合索引列順序會影響到執行計劃對數據行的預估呢?

 

 

 

 

首先來看第一個索引時候的預估演算法:

  這個查詢他預估為4127.86行,如下圖

 

  說起來預估,就離不開統計信息,首先來看IDX_COL2_COL3這個索引的統計信息,
  我們知道,對於複合索引,統計信息中只有前導列的統計數據,也就是說IDX_COL3_COL2這個索引只有COL2這個列的統計信息,如下截圖
  對於COL2=2的統計信息,統計為100336行,我們記住這個數字

 

 

  統計信息的另外一個特點就是在會在查詢列(非索引列)上自動創建統計信息,如下截圖
  查詢執行過程中,自動創建了一個名字為:_WA_Sys_00000003_24E8431A的統計信息
  這個統計信息就是對COL3列的統計,可以發現在大於等於2012-10-20之後的統計行數


  在SQL Server 2012中,對數據行的預估計算方式是各個欄位的選擇性的乘積,
  假如Pn代表不同欄位的密度,那麼預估行數的計算方法就是: 預估行數=p0*p1*p2*p3……*RowCount
  可以利用這個演算法,計算目前數據下,預估出來的結果:4217.86,跟執行計劃預估是一致的,非常完美!

 

 

 

    當刪除了IDX_COL2_COL3重建建立順序為COL3+COL2的索引的時候,預估如下

   與上面同樣的查詢條件,預估為2414.91行

 

   

  依據上面的分析步驟,首先來分析索引列上的統計信息,如下截圖為大於等於2016-10-20之後的預估行數

 

 

同理,本次查詢也會自動建立COL2列上的統計信息(IDX_COL2_COL3索引被刪除),觀察這個統計信息對COL2=2的預估為83711.36行

   

   同樣我們利用上述公式,來計算預估的行數:2414.9035行,也非常完美地吻合和執行計劃預估的結果

   

 

  至此,應該很清楚一開始的問題了,就是為什麼複合索引列順序不一致,在查詢的時候導致預估也不一致的原因。
  最根本的原因有就是:
  符合索引上只有前導列的統計信息,查詢引擎會根據需要自動創建非前導列的統計信息,
  但是,非常關鍵一點,如果細心的話,你會發現查詢引擎自動創建的統計信息的取樣行數都不是100%取樣的,這一點非常關鍵
  正是因為非前導列取樣有一定的誤差,導致在預估演算法的時候,也即 預估行數=p0*p1*p2*p3……*RowCount的時候,密度值是不一樣的
  也即在創建IDX_COL2_COL3的時候,統計出來的COL2密度為P1_1,COL3密度為P2_1
  創建IDX_COL3_COL2的時候,統計出來的COL2密度為P1_2,COL3密度為P2_2,因為P1_1<>P1_2,P2_1<>P2_2
  因此,計算出的結果就是P1_1*P2_1<>P2_1*P2_2,原理很簡單,希望看官能明白。

  

 

  照這麼計算,對於兩個順序不同的統計信息,如果P1_1=P2_1並且P2_1=P2_2,那麼乘積就是一樣的,預估行數也就是一樣的,那麼是不是呢?

  


  對於不同順序的兩個索引,先看COL2,COL3順序的索引
  在查詢一次之後(建立了統計信息),執行一個百分之百取樣(WITH FULLSCAN)的統計信息更新
  重新來看其預估行數,這一次預估為:2894.49

  

 

 

   刪除COL2,COL3順序的索引,建立COL3,COL2為順序的索引
  在查詢一次之後(建立了統計信息),執行一個百分之百取樣(WITH FULLSCAN)的統計信息更新
  重新來看其預估行數,這一次預估為:同樣為2894.49,是吻合上述演算法

 

 

 

 總結:

  文本簡單演示了執行計劃利用統計信息預估的演算法和原理,以及在計算預估行數時候可能受到的干擾因素,
  這就要求我們在建立索引的時候,不僅僅是說我建一個複合索引就完事了,也要註意其索引列的順序對執行計劃預估的影響,
  更重要的是,要註意查詢引擎自動生成的統計信息對預估的影響程度。

  拋開統計信息談索引的,都是耍流氓。拋開統計信息取樣百分比談統計信息的,也是耍流氓。

  

  引申出來另外一個問題:維護統計信息的時候,能只更新索引列的統計信息,忽略非索引列的統計信息嗎?

 

本人技術能力還很菜,寫的不對的地方還請各位看官指出,謝謝。

 


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

-Advertisement-
Play Games
更多相關文章
  • 今天在思考postgresql裡面鎖是怎麼實現的,討論了暫時認為是master進程維護一張表,在各個語句獲取鎖的時候,查詢該表能獲取對應的鎖就繼續,否則就等待,執行完成後釋放鎖。 後面我再去研究到底怎麼實現的,今天先實現怎麼查看某表當前有哪些鎖在上面。 會話1: 事物不提交,在事物2中查詢表test ...
  • 《SQL Server 從入門到精通》 第1章 資料庫基礎 1.2 資料庫的體繫結構 1.2.1 資料庫三級模式結構 1. 模式 模式也稱邏輯模式或概念模式,它是資料庫中 ,是所有用戶的公共數據視圖。一個資料庫只有一個模式,模式處於三級結構的中間層。 2. 外模式 外模式也稱用戶模式,它是 ,`是數 ...
  • 在MS SQL Server中,我們想判斷一個字元串中是否包含有特殊字元。由於徨字元集過多,我們可以使用正則來實現。除了大小字母和數字之外全是特殊字元,因此可以使用這個表達式:[^a-zA-Z0-9]參考下麵代碼示例: ...
  • 昨晚有實現一個小功能,就是在MS SQL Server中,檢查字元串是否包含有大小寫字母。通常應用在字元串的複雜度。 DECLARE @s NVARCHAR(40) = N'SDFfgGRYJhhTYUJ' IF LOWER(@s) COLLATE Latin1_General_CS_AS <> @ ...
  • 在SQL Server中啟用CLR,可以執行下麵SQL語句: EXEC sp_configure 'clr enabled'; EXEC sp_configure 'clr enabled' , '1'; RECONFIGURE; ...
  • 1. 找到MySQL的配置文件,一般在MySQL的安裝目錄下,例如我的: C:\Program Files\MySQL\MySQL Server 5.7 ,打開下麵的一個配置文件: my-default.ini ,在最後面添加一行配置: show_compatibility_56 = 1 。 2. ... ...
  • zookeeper的安裝(圖文詳解。。。來點擊哦!) 一、伺服器的配置 三台伺服器: 192.168.83.133 sunshine 192.168.83.134 sunshineMin 192.168.83.135 sunshineMax 在每台伺服器的hosts文件中添加:(命令:vi /etc ...
  • MongoDB的訪問控制能夠有效保證資料庫的安全,訪問控制是指綁定Application監聽的IP地址,設置監聽埠,使用賬戶和密碼登錄 一,訪問控制的參數 1,綁定IP地址 mongod 參數:--bind_ip <ip address> 預設值是所有的IP地址都能訪問,該參數指定MongoDB對 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...