杂谈--从基数评估来看问题1
前段時間遇到很多例統計信息更新不及時導致執行計劃較差引發性能問題的情況,現在總結分析下,與各位分享。
問題描述:
訂單表用于存放用戶訂單信息,其中有字段DT存放訂單的創建時間,PID存放用戶編號,根據業務需求,我們分別創建在列DT上索引IDX_DT,在PID上創建索引IDX_PID,我們通常會在業務低峰期進行索引維護和統計更新,在雙11期間,訂單暴增而統計信息沒有得到及時更新,部分查詢選用了不合適的索引,導致性能較差。
問題演示:
首先我們生成100W的數據,并將統計更新到最新。
DROP TABLE TB001 GO CREATE TABLE TB001 (ID INT IDENTITY(1,1) PRIMARY KEY,PID INT DEFAULT 0,DT DATETIME DEFAULT GETDATE(),CT CHAR(500) DEFAULT '0' ) GO --導入100W數據 INSERT INTO TB001(CT) SELECT TOP(20000) T2.name FROM sys.all_columns T2 CROSS JOIN sys.all_objects T1 GO 50 --更新DT字段 UPDATE TB001 SET DT=DATEADD(MINUTE,ID,GETDATE()),PID=ID%100000 GO--創建索引 CREATE INDEX IDX_PID ON TB001(PID)CREATE INDEX IDX_DT ON TB001(DT) GO查看PID上統計信息
DBCC SHOW_STATISTICS('TB001','IDX_PID')查看DT上的統計信息
DBCC SHOW_STATISTICS('TB001','IDX_DT')然后模擬新增15W數據,新增的數據的創建時間均大于統計生成的時間。
INSERT INTO TB001(PID,DT,CT) SELECT RID%100000, DATEADD(MINUTE,1000000+RID,GETDATE()), name FROM( SELECT ROW_NUMBER()OVER(ORDER BY name) AS RID, name FROM (SELECT TOP(150000) T2.name FROM sys.all_columns T2CROSS JOIN sys.all_objects T1 ) AS T3 ) AS T4查看最后5w訂單的時間
SELECT MAX(DT) AS MAX_DT, MIN(DT) AS MIN_DT FROM ( SELECT TOP(50000) * FROM TB001 ORDER BY id DESC ) AS T1雖然在訂單表中新增了15W訂單呢,但是這15萬訂單被平均分攤,每個用戶只新增1.5個訂單,每個用戶平均有11.5個訂單,因此如果要查詢2016-09-29 14:39:52.973到2016-11-03 07:58:52.973期間某個用戶的訂單的話,走IDX_PID會是最佳選擇,但執行計劃選擇了IDX_DT的索引。
--表 'TB001'。掃描計數 1,邏輯讀取 150109 次,物理讀取 0 次,預讀 0 次, --lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SELECT * FROM TB001 WHERE DT>'2017-01-11 19:03:46.460' AND DT<'2017-02-15 12:22:46.460' AND PID=10如果我們強制執行計劃走索引:
--表 'TB001'。掃描計數 1,邏輯讀取 324 次,物理讀取 0 次,預讀 0 次, --lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SELECT * FROM TB001 WITH(INDEX=IDX_PID) WHERE DT>'2017-01-11 19:03:46.460' AND DT<'2017-02-15 12:22:46.460' AND PID=10或修改查詢,避免使用索引IDX_DT:
--表 'TB001'。掃描計數 1,邏輯讀取 324 次,物理讀取 0 次,預讀 0 次, --lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。 SELECT * FROM TB001 WITH(INDEX=IDX_PID) WHERE DT+0>'2017-01-11 19:03:46.460' AND DT+0<'2017-02-15 12:22:46.460' AND PID=10?
--=====================================================================
在SQL SERVER 2014之前版本中,對于超出統計信息范圍的參數,基數評估認為其不存在,評估行數為1。在Demo中,由于DT的兩個參數均不在統計信息IDX_DT的直方圖范圍內,認為滿足DT條件的數據為1,因此認定為使用IDX_DT索引為最優。
此類問題針對的是遞增類型的數據,如自增ID,創建時間,貨物批號等,隨著時間推移,新增的數據總是超出統計信息的范圍,當查詢這些新增數據并且執行計劃重新生成時,就可能導致執行計劃出現問題,這也是我們常說的“統計信息未及時更新導致執行計劃問題”。
--=====================================================================
解決辦法:
1. 對遞增類數據提高統計的更新頻率(更新頻率過快也是問題啊)
2. 升級到2014版本(在CdinalityEstimationModeVersion=120下,會采用新的預估算法,不過誰無事玩升級啊)
3. 使用查詢提示強制使用索引(是個辦法,一般也不這么玩)
4. 修改SQL(我目前采用的辦法,使查詢無法使用索引IDX_DT)
?
--====================================================================
很早拜讀過群里一位大神Fanr_Zh的博客《SQL Server 2014新特性——基數評估(白皮書閱讀筆記)》,感悟頗多,結合最近遇到的一些性能問題,弄個Demo與各位看官一起學習下!再次拜謝下Fanr。
--====================================================================
?
轉載于:https://www.cnblogs.com/TeyGao/p/4154803.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的杂谈--从基数评估来看问题1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]linq to sql (Grou
- 下一篇: 关于百度音乐盒