Не впевнений, що це помилка, сама по собі, але це, безумовно, цікаве явище. Відновлення розділів в Інтернеті є новими в SQL Server 2014, тому можуть бути вирішені деякі внутрішні можливості.
Ось моє найкраще пояснення для вас. Зростаюча статистика абсолютно вимагає вибірки всіх розділів з однаковою швидкістю, щоб, коли двигун об'єднує сторінки статистики, можна бути впевненим, що вибірковий розподіл можна порівняти. REBUILD
обов'язково вибіркові дані зі 100% -ною вибірковою швидкістю. Немає гарантій, що 100% вибірки на розділі 9 завжди буде точним показником вибірки для решти розділів. Через це здається, що двигун не може злити зразки, і ви закінчитеся з порожньою статистикою. Однак об’єкт статистики все ще існує:
select
check_time = sysdatetime(),
schema_name = sh.name,
table_name = t.name,
stat_name = s.name,
index_name = i.name,
stats_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
s.stats_id,
s.has_filter,
s.is_incremental,
s.auto_created,
sp.last_updated,
sp.rows,
sp.rows_sampled,
sp.unfiltered_rows,
modification_counter
from sys.stats s
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
left join sys.indexes i
on s.object_id = i.object_id
and s.name = i.name
outer apply sys.dm_db_stats_properties(s.object_id, s.stats_id) sp
where t.name = 'TransactionHistory' and sh.name = 'dbo'
Можна залити крап будь-якою кількістю засобів:
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;
або
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);
або ви можете дочекатися оновлення AutoStats при першій компіляції плану запитів за допомогою цього об’єкта:
-- look at my creative query
select *
from dbo.TransactionHistory
where TransactionDate = '20140101';
Сказавши все це, цей просвітницький пост Ерін Стеллато підкреслює те, що стало сприйматися як основний недолік додаткової статистики. Дані рівня їх розділів оптимізатором не використовуються при формуванні плану запитів, що зменшує передбачувану перевагу додаткової статистики. У чому ж полягає поточна користь додаткової статистики? Я стверджую, що їх основна корисність полягає у здатності вибирати великі таблиці більш послідовно з більшою швидкістю, ніж у традиційних статистичних даних.
Використовуючи ваш приклад, ось як виглядають речі:
set statistics time on;
update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;
--SQL Server Execution Times:
-- CPU time = 94 ms, elapsed time = 131 ms.
update statistics dbo.TransactionHistory(IDX_ProductId)
with resample on partitions(2);
--SQL Server Execution Times:
-- CPU time = 0 ms, elapsed time = 5 ms.
drop index IDX_ProductId On dbo.TransactionHistory;
CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId)
WITH (DATA_COMPRESSION = ROW)
ON [PRIMARY]
update statistics dbo.TransactionHistory(IDX_ProductId)
with fullscan;
--SQL Server Execution Times:
-- CPU time = 76 ms, elapsed time = 66 ms.
Повне оновлення статистичних даних щодо додаткової статистики витрат 131 мс. Повне статистичне оновлення статистики, що не відповідає рівням статистики, становить 66 мс. Неблокова статистика є повільнішою, швидше за все, через накладні витрати, пов'язані з об'єднанням окремих сторінок статистики назад в основну гістограму. Однак, використовуючи статистичний об'єкт, орієнтований на розділи, ми можемо оновити один розділ і об'єднати його назад в основний блок гістограми за 5 мс. Тож у цей момент адміністратор із додатковою статистикою стикається з рішенням. Вони можуть скоротити загальний час ведення статистики, лише традиційно потребує оновлення розділів, або вони можуть експериментувати з більш високими показниками вибірки, щоб вони могли отримати більше рядків, відібраних за той же проміжок часу, що і їх попередній термін обслуговування. Перший дозволяє дихати кімнатою у вікні технічного обслуговування, другий може висувати статистику за дуже великою таблицею до місця, де запити отримують кращі плани на основі більш точної статистики. Це не гарантія, і ваш пробіг може відрізнятися.
Читач може побачити, що 66 мс не є болісним часом оновлення статистики в цій таблиці, тому я спробував встановити тест на наборі даних stackexchange. У недавньому дампа, який я завантажив, є 6,418,608 публікацій (за винятком публікацій StackOverflow та всіх публікацій з 2012 року - помилка даних з мого боку).
Я розділив дані по [CreationDate]
... демо.
Ось декілька термінів для деяких досить стандартних сценаріїв (100% - перебудова індексу, за замовчуванням - статистика автоматичного оновлення або UPDATE STATISTICS
без вказаної частоти вибірки:
- Створіть непосильну статистику за допомогою програми Fullscan: час процесора = 23500 мс, минулий час = 22521 мс.
- Створіть поступову статистику WIth Fullscan: час процесора = 20406 мс, минулий час = 15413 мс.
- Оновіть непосильну статистику за допомогою частоти вибірки за замовчуванням: час процесора = 406 мс, минулий час = 408 мс.
- Оновіть додаткову статистику за частотою вибірки за замовчуванням: час процесора = 453 мс, минулий час = 507 мс.
Скажімо, ми більш досконалі, ніж ці сценарії за замовчуванням, і вирішили, що 10% вибіркової ставки - це мінімальна ставка, яка повинна дати нам необхідні плани, зберігаючи час технічного обслуговування до розумних часових рамків.
- Оновіть непосильну статистику зразком 10 відсотків: час процесора = 2344 мс, минулий час = 2441 мс.
- Оновіть додаткову статистику зразком 10 відсотків: час процесора = 2344 мс, минулий час = 2388 мс.
Поки немає чіткої користі від збільшення покрокової статистики. Однак якщо ми будемо використовувати недокументований sys.dm_db_stats_properties_internal()
DMV (нижче), ви можете отримати деяку інформацію про те, який розділ (и) ви можете оновити. Скажімо, ми внесли зміни до даних у розділі 3 і хочемо, щоб статистика була нова для вхідних запитів. Ось наші варіанти:
- Оновлення не-додаткове оновлення за замовчуванням (також поведінка за замовчуванням Автоматичного оновлення): 408 мс.
- Оновіть неінкрементацію на 10%: 2441 мс.
- Оновіть додаткову статистику, розділ 3 за допомогою Resample (10% - наша визначена частота вибірки): час процесора = 63 мс, минулий час = 63 мс.
Ось де нам потрібно прийняти рішення. Чи візьмемо виграш 63 мс. оновлення статистики на основі розділів, чи ми збільшуємо показник вибірки ще вище? Скажімо, ми готові прийняти початковий показник вибірки на рівні 50% на основі додаткової статистики:
- Оновіть додаткову статистику на 50%: минув час = 16840 мс.
- Оновіть додаткову статистику, розділ 3 за допомогою Resample (50% - наш новий час оновлення): минуло час = 295 мс.
Ми можемо вибирати набагато більше даних, можливо, налаштовуючи оптимізатор, щоб краще здогадуватися про наші дані (хоча він ще не використовує статистику рівня розділів), і ми можемо зробити це швидше зараз, коли у нас є додаткова статистика.
Хоча одна остання цікава річ. Що з оновленнями синхронної статистики? Чи збережена 50% частота вибірки, навіть коли починається автозапуск?
Я видалив дані з розділу 3 і запустив запит на CreationDate і перевірив, а потім перевірив ставки з тим самим запитом, що вказаний нижче. Збережено 50% вибірки.
Отже, короткий короткий сюжет: додаткова статистика може бути корисним інструментом при правильному обмірі думок та початкових роботах із налаштування. Однак ви повинні знати проблему, яку ви намагаєтеся вирішити, і тоді вам потрібно її вирішити належним чином. Якщо ви отримуєте погані оцінки потужності, ви могли б бути в змозі отримати кращі плани з стратегічної частотою дискретизації і деякі інвестованого втручання. Однак ви отримуєте лише невелику частину переваги, оскільки використовувана гістограма являє собою єдину, об’єднану сторінку статистики, а не інформацію про рівень розділу. Якщо ви відчуваєте біль у вікні технічного обслуговування, то, можливо, додаткова статистика може вам допомогти, але, ймовірно, вам знадобиться налаштувати процес втручання технічного обслуговування з високим дотиком. Незалежно,:
- Статистика, створена за допомогою індексів, не узгоджених розділами з базовою таблицею.
- Статистика, створена на читаються вторинні бази даних AlwaysOn.
- Статистика, створена на базі даних лише для читання.
- Статистика створена за відфільтрованими індексами.
- Статистика створена за переглядами.
- Статистика, створена на внутрішніх таблицях.
- Статистика, створена за допомогою просторових індексів або XML-індексів.
Сподіваюся, це допомагає
select
sysdatetime(),
schema_name = sh.name,
table_name = t.name,
stat_name = s.name,
index_name = i.name,
leading_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
s.stats_id,
parition_number = isnull(sp.partition_number,1),
s.has_filter,
s.is_incremental,
s.auto_created,
sp.last_updated,
sp.rows,
sp.rows_sampled,
sp.unfiltered_rows,
modification_counter = coalesce(sp.modification_counter, n1.modification_counter)
from sys.stats s
join sys.tables t
on s.object_id = t.object_id
join sys.schemas sh
on t.schema_id = sh.schema_id
left join sys.indexes i
on s.object_id = i.object_id
and s.name = i.name
cross apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) sp
outer apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) n1
where n1.node_id = 1
and (
(is_incremental = 0)
or
(is_incremental = 1 and sp.partition_number is not null)
)
and t.name = 'Posts'
and s.name like 'st_posts%'
order by s.stats_id,isnull(sp.partition_number,1)