Розглянемо простий план запитів та виконання запитів AdventureWorks, показаний нижче. Запит містить предикати, пов'язані з AND
. Оцінка кардинальності оптимізатора - 41 211 рядків:
-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
Використання статистики за замовчуванням
Враховуючи лише статистику на один стовпчик, оптимізатор виробляє цю оцінку шляхом оцінки кардинальності для кожного предиката окремо та множення отриманих селективностей разом. Це евристика передбачає, що предикати повністю незалежні.
Розбиття запиту на дві частини полегшує бачення розрахунку:
-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336;
Таблиця історії транзакцій містить 113,443 рядків, тому оцінка 68 336,4 представляє вибірковість для цього предиката 68336,4 / 113443 = 0,60238533 . Ця оцінка отримується з використанням інформації гістограми для TransactionID
стовпця та постійних значень, зазначених у запиті.
-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
Цей предикат має оцінну вибірковість 68413,0 / 113443 = 0,60306056 . Знову ж таки, вона обчислюється з постійних значень предиката та гістограми TransactionDate
об’єкта статистики.
Якщо припустити, що предикати є абсолютно незалежними, ми можемо оцінити вибірковість двох предикатів разом, множивши їх разом. Остаточну оцінку кардинальності отримують шляхом множення отриманої селективності на 113,443 рядки в базовій таблиці:
0.60238533 * 0.60306056 * 113443 = 41210.987
Після округлення це оцінка 41,211, що спостерігається в оригінальному запиті (оптимізатор також використовує математику з плаваючою точкою всередині).
Не велика оцінка
У наборі даних TransactionID
та TransactionDate
стовпці є тісна кореляція у наборі даних AdventureWorks (як це часто монотонно збільшуються ключі та стовпці дати). Це співвідношення означає, що припущення про незалежність порушено. Як наслідок, план запиту після виконання показує 68 095 рядків, а не оцінені 41 211:
Слідовий прапор 4137
Увімкнення цього прапора трасування змінює евристику, що використовується для об'єднання предикатів. Замість того, щоб вважати повну незалежність, оптимізатор вважає, що вибірковість двох предикатів досить близька, щоб вони могли бути співвіднесеними:
-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);
Нагадаємо, що TransactionID
один присудок оцінював 68 366,4 рядків іTransactionDate
один присудок оцінював 68 413 рядків. Оптимізатор вибрав нижчу з цих двох оцінок, а не множення вибірковості.
Це, звичайно, лише інша евристика, але така, яка може допомогти покращити оцінки для запитів із співвіднесеними AND
предикатами. Кожен предикат вважається можливим співвіднесенням, і інші коригування вносяться, коли AND
задіяно багато пропозицій, але цей приклад слугує для показу основ цього.
Статистика в багатьох стовпцях
Вони можуть допомогти у запитах із співвідношеннями, але інформація гістограми все ще базується виключно на провідному стовпчику статистики. Такі статистичні дані щодо кількох стовпців-кандидатів відрізняються важливим чином:
CREATE STATISTICS
[stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
(TransactionID, TransactionDate);
CREATE STATISTICS
[stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
(TransactionDate, TransactionID);
Взявши лише одне з них, ми можемо побачити, що єдиною додатковою інформацією є додаткові рівні щільності "всі". Гістограма все ще містить лише детальну інформацію про TransactionDate
стовпчик.
DBCC SHOW_STATISTICS
(
'Production.TransactionHistory',
'stats Production.TransactionHistory TransactionDate TransactionID'
);
Завдяки цій статистиці багато стовпців ...
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE
TH.TransactionID BETWEEN 100000 AND 168336
AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';
... план виконання показує оцінку, яка точно така ж, як і коли була доступна лише одна стовпецька статистика:
Statistics objects on multiple columns also store statistical information about the correlation of values among the columns