Чи оновлює статистику повторного індексу?


43

Я проходив курс MS10775A минулого тижня, і одне питання, на яке тренер не міг надійно відповісти, це:

Чи оновлює статистику повторний індекс?

Ми знайшли дискусії в Інтернеті, стверджуючи, що це робить, а що ні.


Корисно зазначити, що REINDEXоновлення статистики стовпців є побічним ефектом відновлення індексу - не потрібно оновлювати статистику. Дані в таблиці не змінюються. Це ті самі дані, він лише a) перемістив своє місце розташування на спінінг-платі (коли реорганізована сторінка) або b) сидячи на іншій сторінці (у разі повторної збірки). Отже: повторний індекс робить (деякі) оновлення статистики: немає необхідності робити це.
Ян Бойд

Відповіді:


51

Ви можете пам’ятати про наступне, коли дбаєте про оновлення статистики (скопійовано з « Перебудова індексів проти оновлення статистики» (Бенджамін Неварес)

  1. За замовчуванням в UPDATE STATISTICSоператорі використовується лише зразок записів таблиці. Використання UPDATE STATISTICS WITH FULLSCANсканує всю таблицю.

  2. За замовчуванням UPDATE STATISTICSоператор оновлює статистику індексу та стовпців. За допомогою цієї COLUMNSопції буде оновлено лише статистику стовпців. Використання INDEXопції оновить лише статистику індексу.

  3. Перебудова індексу , наприклад, за допомогою використання ALTER INDEX … REBUILD, також буде оновлювати статистику індексу з еквівалентом використання, WITH FULLSCAN якщо таблиця не розділена, і в цьому випадку статистика вибирається лише (стосується SQL Server 2012 та пізніших версій).

  4. Статистика, створена вручну за допомогою CREATE STATISTICS, не оновлюється жодною ALTER INDEX ... REBUILDоперацією, в тому числі ALTER TABLE ... REBUILD. ALTER TABLE ... REBUILDробить оновлення статистики для кластерного індексу, якщо він визначений у таблиці, що перебудовується.

  5. Реорганізація індексу , наприклад, використання ALTER INDEX … REORGANIZEне оновлює будь-яку статистику.

Коротка відповідь полягає в тому, що вам потрібно використовувати UPDATE STATISTICSдля оновлення статистики стовпців і що відбудова індексу оновлюватиме лише статистику індексу. Ви можете примусити оновити всю статистику в таблиці, включаючи статистику індексу та статистику, створену вручну, за допомогою UPDATE STATISTICS (tablename) WITH FULLSCAN;синтаксису.

Наступний код ілюструє правила, капсульовані вище:

Спочатку ми створимо таблицю з парою стовпців та кластерним індексом:

USE tempdb;

IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;

CREATE TABLE dbo.SomeTable
(
    rn int NOT NULL IDENTITY(1,1)
        CONSTRAINT pk
        PRIMARY KEY NONCLUSTERED
    , i int NOT NULL INDEX i 
    , d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);

CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);

CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;

INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;

Цей запит показує дату останнього оновлення кожного об'єкта статистики:

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

Результати показують, що оновлення ще не відбулося, що правильно, оскільки ми щойно створили таблицю:

╔═══════════════╦═══════════╦═══════════╗
Ame Ім'я об’єкта ame Ім'я статистики ║ СтатДейт ║
╠═══════════════╬═══════════╬═══════════╣
║ dbo.SomeTable ║ cx ║ NULL ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═══════════╝

Давайте відновимо всю таблицю і подивимось, чи це оновлення статистики:

ALTER TABLE dbo.SomeTable REBUILD;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
Ame Ім'я об’єкта ame Ім'я статистики ║ СтатДейт ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ NULL ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Результати показують, що оновлено лише кластерні статистичні показники .

Далі виконуємо дискретну UPDATE STATSоперацію:

UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';

Як бачите, ми щойно оновлювали статистику dстовпця:

╔═══════════════╦═══════════╦═════════════════════ ════╗
Ame Ім'я об’єкта ame Ім'я статистики ║ СтатДейт ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║
║ dbo.SomeTable ║ i ║ NULL ║
║ dbo.SomeTable ║ pk ║ NULL ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.597 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Тепер ми оновимо статистику для всієї таблиці:

UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;

SELECT ObjectName = sc.name + N'.' + o.name
    , StatsName = s.name
    , StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
    INNER JOIN sys.objects o ON s.object_id = o.object_id
    INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
    AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗
Ame Ім'я об’єкта ame Ім'я статистики ║ СтатДейт ║
╠═══════════════╬═══════════╬═════════════════════ ════╣
║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ i ║ 2018-09-17 14: 09: 13.600 ║
║ dbo.SomeTable ║ pk ║ 2018-09-17 14: 09: 13.603 ║
║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.607 ║
╚═══════════════╩═══════════╩═════════════════════ ════╝

Як бачите, єдиний спосіб бути впевненим, що всі статистичні дані оновлюються - це або оновлювати кожну вручну, або оновлювати всю таблицю UPDATE STATISTICS (table);.


@JeremyWeir - як видно з прикладу коду, який я щойно додав до вищезазначеного питання, єдиними оновленими статистичними даними є ті, які явно оновлюються або через ALTER INDEX ... REBUILDабо через UPDATE STATISTICSзаяву. Якщо сама таблиця перебудована, оновлюється лише статистика кластерних індексів. FYI, первинний ключ та кластерний індекс не обов'язково підтримуються одним і тим же об'єктом індексу.
Макс Вернон

5

На сторінці "Документи Microsoft" для статистики SQL Server зазначено :

Такі операції, як перебудова, дефрагментація або реорганізація індексу, не змінюють розподіл даних. Тому вам не потрібно оновлювати статистику після виконання операцій ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG або ALTER INDEX REORGANIZE . Оптимізатор запитів оновлює статистику під час перебудови індексу на таблиці або перегляду за допомогою ALTER INDEX REBUILD або DBCC DBREINDEX, однак це оновлення статистики є побічним продуктом відновлення індексу. Оптимізатор запитів не оновлює статистику після операцій DBCC INDEXDEFRAG або ALTER INDEX REORGANIZE.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.