Уникальные обновления индексов и счетчики модификаций строк статистики

14

Учитывая следующую таблицу, уникальный кластерный индекс и статистику:

CREATE TABLE dbo.Banana
(
    pk integer NOT NULL, 
    c1 char(1) NOT NULL, 
    c2 char(1) NOT NULL
);

CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);

CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);

INSERT dbo.Banana 
    (pk, c1, c2) 
VALUES 
    (1, 'A', 'W'), 
    (2, 'B', 'X'), 
    (3, 'C', 'Y'), 
    (4, 'D', 'Z');

-- Populate statistics
UPDATE STATISTICS dbo.Banana;

Пример данных

Счетчики модификации строки статистики, очевидно, показывают ноль перед любыми обновлениями:

-- Show statistics modification counters
SELECT
    stats_name = S.[name], 
    DDSP.stats_id,
    DDSP.[rows],
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.object_id, S.stats_id) AS DDSP
WHERE
    S.[object_id] = OBJECT_ID(N'dbo.Banana', N'U');

Счетчики нулевой модификации

Увеличение значения каждого pkстолбца по одному для каждой строки:

-- Increment pk in every row
UPDATE dbo.Banana 
SET pk += 1;

Использует план выполнения:

Сплит Сортировать Свернуть план выполнения

Он производит следующие счетчики изменений статистики:

Счетчики модификаций после обновления

Вопросов

  1. Что делают операторы Split, Sort и Collapse?
  2. Почему pkстатистика показывает 2 модификации, но c1и c2показать 5?
Пол Уайт 9
источник

Ответы:

15

SQL Server всегда использует сочетание операторов Split, Sort и Collapse при ведении уникального индекса как часть обновления, которое влияет (или может влиять) на несколько строк.

Работая с примером в вопросе, мы могли бы написать обновление как отдельное однострочное обновление для каждой из четырех представленных строк:

-- Per row updates
UPDATE dbo.Banana SET pk = 2 WHERE pk = 1;
UPDATE dbo.Banana SET pk = 3 WHERE pk = 2;
UPDATE dbo.Banana SET pk = 4 WHERE pk = 3;
UPDATE dbo.Banana SET pk = 5 WHERE pk = 4;

Проблема в том, что первый оператор потерпит неудачу, поскольку он изменяется pkс 1 на 2, и уже есть строка, где pk= 2. Механизм хранения SQL Server требует, чтобы уникальные индексы оставались уникальными на каждом этапе обработки, даже в пределах одного оператора. , Это проблема, решаемая с помощью Split, Sort и Collapse.

Трещина Трещина

Первым шагом является разделение каждого оператора обновления на удаление с последующей вставкой:

DELETE dbo.Banana WHERE pk = 1;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');

DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');

DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');

DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Оператор Split добавляет столбец кода действия в поток (здесь он помечен как Act1007):

Сплит недвижимость

Код действия: 1 для обновления, 3 для удаления и 4 для вставки.

Сортировать Сортировать

Вышеуказанные операторы split по-прежнему приводят к ложному временному нарушению уникального ключа, поэтому следующим шагом будет сортировка операторов по ключам обновляемого уникального индекса ( pkв данном случае), а затем по коду действия. Для этого примера это просто означает, что delete (3) на том же ключе упорядочены перед вставками (4). Итоговый порядок:

-- Sort (pk, action)
DELETE dbo.Banana WHERE pk = 1;
DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');
DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');
DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Сортировать свойства

коллапс коллапс

Предшествующего этапа достаточно, чтобы гарантировать избежание ложных нарушений уникальности во всех случаях. В качестве оптимизации Collapse объединяет смежные удаления и вставляет одно и то же значение ключа в обновление:

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Пары удаления / вставки для pkзначений 2, 3 и 4 были объединены в обновление, в результате чего единственное удаление при pk= 1, а вставка при pk= 5.

Оператор свертывания группирует строки по ключевым столбцам и обновляет код действия для отражения результата свертывания:

Свернуть свойства

Обновление кластерного индекса Обновление кластерного индекса

Этот оператор помечен как Обновление, но он способен вставлять, обновлять и удалять. То, какое действие выполняет обновление кластеризованного индекса для строки, определяется значением кода действия в этой строке. У оператора есть свойство Action, отражающее этот режим работы:

Свойство действия Обновление кластерного индекса


Счетчики модификации строк

Обратите внимание, что три вышеприведенных обновления не изменяют ключ (и) поддерживаемого уникального индекса. По сути, мы преобразовали обновления ключевых столбцов в индексе в обновления неключевых столбцов ( c1и c2), а также удаления и вставки. Ни удаление, ни вставка не могут привести к ложному нарушению уникального ключа.

Вставка или удаление влияют на каждый столбец в строке, поэтому счетчики изменений, связанные с каждым столбцом, будут увеличиваться. При обновлении (обновлениях) только статистические данные с любым из обновленных столбцов в качестве ведущего столбца увеличивают свои счетчики изменений (даже если значение не изменяется).

Поэтому счетчики изменений строки статистики показывают 2 изменения pk, и 5 для c1и c2:

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;                         -- All columns modified
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;  -- c1 and c2 modified
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');    -- All columns modified

Примечание. Только изменения, примененные к базовому объекту (куча или кластерный индекс), влияют на счетчики изменений строк статистики. Некластеризованные индексы являются вторичными структурами, отражающими изменения, уже внесенные в базовый объект. Они вообще не влияют на счетчики модификации строк статистики.

Если объект имеет несколько уникальных индексов, отдельная комбинация Split, Sort, Collapse используется для организации обновлений каждого из них. SQL Server оптимизирует этот случай для некластеризованных индексов, сохраняя результат Split в буферную таблицу Eager, а затем воспроизводит этот набор для каждого уникального индекса (который будет иметь свою собственную сортировку по ключам индекса + код действия и Collapse).

Влияние на обновления статистики

Автоматическое обновление статистики (если включено) происходит, когда оптимизатору запросов требуется статистическая информация и он отмечает, что существующая статистика устарела (или недействительна из-за изменения схемы). Статистика считается устаревшей, когда количество зарегистрированных изменений превышает пороговое значение.

Расположение «Сплит / Сортировка / Свернуть» приводит к различным модификаций строк, чем ожидалось. Это, в свою очередь, означает, что обновление статистики может быть инициировано раньше или позже, чем было бы в противном случае.

В приведенном выше примере количество модификаций строки для ключевого столбца увеличивается на 2 (чистое изменение), а не на 4 (по одному на каждую затронутую строку таблицы) или на 5 (по одному на каждое удаление / обновление / вставку, созданное в Свернуть).

Кроме того, неключевые столбцы, которые логически не были изменены исходным запросом, накапливают модификации строк, которые могут насчитывать до двух обновленных строк таблицы (по одному для каждого удаления и по одному для каждой вставки).


Количество записанных изменений зависит от степени перекрытия между старыми и новыми значениями ключевого столбца (и, таким образом, степень, в которой отдельные удаления и вставки могут быть свернуты). Сбрасывая таблицу между каждым выполнением, следующие запросы демонстрируют влияние на счетчики модификации строк с разными перекрытиями:

UPDATE dbo.Banana SET pk = pk + 0; -- Full overlap

рк = рк + 0

UPDATE dbo.Banana SET pk = pk + 1;

рк = рк + 1

UPDATE dbo.Banana SET pk = pk + 2;

рк = рк + 2

UPDATE dbo.Banana SET pk = pk + 3;

рк = рк + 3

UPDATE dbo.Banana SET pk = pk + 4; -- No overlap

рк = рк + 4

Пол Уайт 9
источник