Sql-Server
LIKE 運算符的基數估計(局部變數)
我的印像是,在
LIKE
對未知場景進行所有優化時,舊版和新版 CE 都使用 9% 的估計值(假設相關統計數據可用並且查詢優化器不必求助於選擇性猜測)。在對信用數據庫執行以下查詢時,我在不同的 CE 下得到不同的估計。在新的 CE 下,我收到了預期的 900 行的估計值,在舊版 CE 下,我收到了 241.416 的估計值,但我無法弄清楚這個估計值是如何得出的。有沒有人能夠闡明任何觀點?
-- New CE (Estimate = 900) DECLARE @LastName VARCHAR(15) = 'BA%' SELECT * FROM [Credit].[dbo].[member] WHERE [lastname] LIKE @LastName; -- Forcing Legacy CE (Estimate = 241.416) DECLARE @LastName VARCHAR(15) = 'BA%' SELECT * FROM [Credit].[dbo].[member] WHERE [lastname] LIKE @LastName OPTION ( QUERYTRACEON 9481, QUERYTRACEON 9292, QUERYTRACEON 9204, QUERYTRACEON 3604 );
在我的場景中,我已經將信用數據庫設置為兼容級別 120,因此為什麼在第二個查詢中我使用跟踪標誌來強制使用舊版 CE,並提供有關查詢優化器使用/考慮哪些統計資訊的資訊。我可以看到正在使用“姓氏”的列統計資訊,但我仍然無法計算出 241.416 的估計值是如何得出的。
除了這篇 Itzik Ben-Gan 文章外,我在網上找不到任何東西,該文章指出“在所有優化未知場景中使用 LIKE 謂詞時,舊版和新版 CE 都使用 9% 的估計值。”。該文章中的資訊似乎不正確。
LIKE
在你的情況下的猜測是基於:
G
: 標準的 9% 猜測 (sqllang!x_Selectivity_Like
)M
:係數 6(幻數)D
:以字節為單位的平均數據長度(來自統計數據),向下舍入為整數具體來說,
sqllang!CCardUtilSQL7::ProbLikeGuess
使用:
Selectivity (S) = G / M * LOG(D)
筆記:
- 如果介於 1 和 2 之間,
LOG(D)
則省略該術語。D
- 如果
D
小於 1(包括缺失或NULL
統計):
D = FLOOR(0.5 * maximum column byte length)
這種古怪和復雜性是原始 CE 的典型特徵。
在問題範例中,平均長度為 5(
DBCC SHOW_STATISTICS
四捨五入後為 5.6154):估計 = 10,000 * (0.09 / 6 * LOG(5)) = **241.416**
其他範例值:
**D** =**使用 S 的公式進行估計** 15 = 406.208 14 = 395.859 13 = 384.742 12 = 372.736 11 = 359.684 10 = 345.388 09 = 329.584 08 = 311.916 07 = 291.887 06 = 268.764 05 = 241.416 04 = 207.944 03 = 164.792 02 = 150.000(未使用日誌) 01 = 150.000(未使用日誌) 00 = 291.887 (LOG 7) /* FLOOR(0.5 * 15) [15 因為姓氏是 varchar(15)] */
試驗台
DECLARE @CharLength integer = 5, -- Set length here @Counter integer = 1; CREATE TABLE #T (c1 varchar(15) NULL); -- Add 10,000 rows SET NOCOUNT ON; SET STATISTICS XML OFF; BEGIN TRANSACTION; WHILE @Counter <= 10000 BEGIN INSERT #T (c1) VALUES (REPLICATE('X', @CharLength)); SET @Counter = @Counter + 1; END; COMMIT TRANSACTION; SET NOCOUNT OFF; SET STATISTICS XML ON; -- Test query DECLARE @Like varchar(15); SELECT * FROM #T AS T WHERE T.c1 LIKE @Like; DROP TABLE #T;