Index--過濾索引和參數化


--============================================

領導指點我去給某台數據庫調優下,結果屁顛屁顛地干完,還自我感覺良好,剛剛別人博客時,才發現自己踩坑了!!

--============================================

有一很簡單查詢SQL,類似:

SELECT * FROM TB1
WHERE C1='C1'
AND C2='C2'
AND C3='C3'
AND C4='C4'

發現該SQL執行很慢,一看是全表掃描,便考慮WHERE條件中每列的可選擇行,表中有700W數據

查看C1的可選擇性

SELECT COUNT(DISTINCT C1) FROM TB1 WITH(NOLOCK)


發現C1列去重后有140W,選擇性比較高,優先作為索引的第一個鍵值列。

SELECT TOP(100) C1,COUNT(1) AS Rcount
FROM TB1
GROUP BY C1
ORDER BY Rcount

結果發現C1列中值為"無效"的行有幾十萬條,其余值最多也才300多條。這就讓我糾結了,數據分布不均勻,很容易導致參數嗅探的問題,趕快訊詢問開發,確認是否會使用“無效”來查詢,得到明確答復不會使用(無用的數據沒有刪除而修改值為無效,好霸氣的做法),於是乎,過濾索引瞬間冒出來

CREATE INDEX IDX_TB1_C1
ON TB1(C1)
WHERE C1<>'無效'
WITH(MAXDOP=6)

多么完美的解決方案啊,自我感覺良好中。。。
-------------------------------------------------------------------------------

過了兩小時,加查索引使用情況

SELECT * FROM sys.dm_db_index_usage_stats
WHERE database_id = DB_ID()
AND object_id=OBJECT_ID('TB1')

發現索引完全沒有被使用,不可能啊,再次檢查SQL腳本

(@P0 NVARCHAR,@P1 int,@P2 int,@P3 int) 
SELECT * FROM TB1
WHERE C1=@P0
AND C2=@P1
AND C3=@P2
AND C4=@P3

以我多年的經驗,我武斷地判斷隱式轉換導致,因為這問題出現不是一次兩次啦,C1列時VARCHAR類型的,於是乎,通知開發改程序,收工!!

--==================================================================================

真的收工了嗎?當然沒有,要不然我還啰嗦啥呢

在Amaranthus的大作中有這樣一句話:

在沒有recompile提示之下,過濾索引和過濾統計信息不會被應用到參數化的字段過濾。(In the absence of a RECOMPILE hint, filtered indexes and statistics will not be used in conjunction with parameterization that refers to the filter column.)

 

對於參數化的過濾條件,查詢優化器無法確認未來傳入的具體值滿足過濾索引中的過濾條件,因此不會考慮使用過濾索引

 

解決辦法:

1. 將索引過濾條件移除(由於查詢不會使用“無效”,因此不會出現參數嗅探問題)

2. 在查詢條件中顯示加入過濾條件(SQL 中加入 AND C1<>'無效',有點畫色添足的感覺)

 

吭只有踩過才知道啊!!!

--====================================================================================

妹子

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM