Налаштування
У мене виникають проблеми з розумінням оцінки кардинальності. Ось моя тестова установка:
- версія 2010 року бази даних переповнення стека
- SQL Server 2017 CU15 + GDR (KB4505225) - 14.0.3192.2
- новий CE (рівень сумісності 140)
Я маю цю процедуру:
USE StackOverflow2010;
GO
CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
@CommentCount int
AS
BEGIN
SELECT *
FROM dbo.Posts p
WHERE
p.CommentCount = @CommentCount
OPTION (RECOMPILE);
END;
GO
У dbo.Posts
таблиці немає некластеризованих індексів чи статистичних даних (є кластерний індекс Id
).
На запит прогнозного плану для цього "розрахункові рядки", які виходять, становлять 1 dbo.Posts
934,99:
EXEC #sp_PostsByCommentCount @CommentCount = 51;
Наступний об’єкт статистики був автоматично створений, коли я запитав прогнозний план:
DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Основні моменти цього:
- Статистика має досить низький рівень вибірки 1,81% (67,796 / 3,744,192)
- Було використано лише 31 крок гістограми
- Значення "Вся щільність"
0.03030303
(33 вибіркових значення були відібрані) - Остання
RANGE_HI_KEY
в гістограмі - 50, зEQ_ROWS
1
Питання
Передача будь-якого значення, що перевищує 50 (аж до 2147,483,647), призводить до оцінки рядків 1 934,99. Який розрахунок або значення використовується для отримання цієї оцінки? Оцінювач застарілої кардинальності, до речі, дає оцінку в 1 рядок.
Що я пробував
Ось деякі теорії, які я мав, те, що я намагався, або додаткові шматочки інформації, які я зміг викопати, переглядаючи це.
Вектор щільності
Спочатку я думав, що це буде вектор густини, такий же, як і колись OPTION (OPTIMIZE FOR UNKNOWN)
. Але вектор щільності для цього об’єкта статистики становить 3,744,192 * 0,03030303 = 113,460, тож це не все.
Розширені події
Я спробував запустити розширений сеанс подій, який зібрав query_optimizer_estimate_cardinality
подію (про яку я дізнався з публікації в блозі Пола Уайта. Оцінка кардинальності: Об'єднання статистики щільності ), і отримав такі цікаві підказки:
<CalculatorList>
<FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000"
CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />
<FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001"
TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true"
StatId="4" />
</CalculatorList>
Отож, здається, використовувався CSelCalcAscendingKeyFilter
калькулятор (інший каже, що не вдався, що б це не означало). Цей стовпець не є ключовим, унікальним або обов'язково висхідним, але все одно.
Виконувати цей термін в Google, привів мене до деяких публікацій у блозі:
- Джо Сак - калькулятор CSelCalcAscendingKeyFilter ,
- Іцік Бен-Ган - Шукайте і ви скануєте Частина II: висхідні ключі
Ці повідомлення вказують на нову основу СЕ ці зовнішні оцінки гістограми на поєднанні вектора щільності та лічильника модифікації стати. На жаль, я вже виключив вектор щільності (я думаю ?!), а лічильник модифікацій дорівнює нулю (у sys.dm_db_stats_properties
будь-якому випадку).
Сліди прапорів
Форест запропонував увімкнути TF 2363, щоб отримати більше інформації про процес оцінки. Я думаю, що найрелевантніше з цього результату:
Plan for computation:
CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)
Selectivity: 0.000516798
Це прорив (спасибі, Форест!): Це 0.000516798
число (яке, здається, було безрезультатно округлене в Selectivity="0.001"
атрибуті XE вище), помножене на кількість рядків у таблиці - це оцінка, яку я шукав (1,934,99).
Я, мабуть, пропускаю щось очевидне, але мені не вдалося інженеру змінити, як це значення вибірковості виробляється всередині CSelCalcAscendingKeyFilter
калькулятора.