MSG 666 при выполнении запроса на вставку в индексированную таблицу с 80М строк


10

Странно, моя хранимая процедура начала получать Msg 666 для некоторых входных данных.

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

Columns:
A_Id: PK, int
B_Id: PK, FK, int
C_Id: PK, FK, int
D_Id: PK, smallint 

По сути, это таблица, которая соединяет все ссылочные объекты вместе.

Indexes:
IX_TableName_D_id - Clustered index on D_id column
PK_TableName - Unique non-clustered index on all columns (A_Id, B_Id, C_Id, D_Id)

Фрагментация по обоим показателям низкая (<25%). Однако фрагментация PK_TableName быстро растет, поскольку объем работы с таблицей довольно интенсивный.

Размер стола:

Row count: ~80,000,000 rows

Итак, когда я пытаюсь выполнить очень простой запрос, для некоторых D_Id я получаю следующее сообщение:

Сообщение 666. Максимальное сгенерированное системой уникальное значение для дублирующейся группы было превышено для индекса с идентификатором раздела 422223771074560. Удаление и повторное создание индекса может решить эту проблему; в противном случае используйте другой ключ кластеризации.

Пример запроса:

INSERT INTO TableName
(A_Id,B_Id,C_Id,D_id)
VALUES (1,1,1,14)

Например, когда я устанавливаю D_Id в некоторые значения - он терпит неудачу, например, «14». Если я установлю D_ID на другие значения (1,2,3, ... 13, 15,16, ...), запрос будет работать нормально.

Я подозреваю, что с индексами происходит что-то действительно плохое ... Но я не могу до конца разобраться ... :( Почему это не получается?

Ответы:


16

Проблема низкой селективности, упомянутая Remus, сама по себе недостаточна, чтобы вызвать проблему в таблице размеров.

Уникализатор начинается с 1и может подниматься до того, 2,147,483,646как фактически выйдет за пределы диапазона.

Это также требует правильного шаблона повторных удалений и вставок, чтобы увидеть проблему.

CREATE TABLE T
(
X SMALLINT,
Y INT IDENTITY PRIMARY KEY NONCLUSTERED
)

CREATE CLUSTERED INDEX IX ON T(X)

INSERT INTO T VALUES (1),(1),(1),(2),(2)

дает

+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 |             |
| 1 | 2 |           1 |
| 1 | 3 |           2 |
| 2 | 4 |             |
| 2 | 5 |           1 |
+---+---+-------------+

Потом работает

DELETE FROM T 
WHERE Y IN (2,3)

INSERT INTO T VALUES (1),(1)

дает

+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 |             |
| 1 | 6 |           3 |
| 1 | 7 |           4 |
| 2 | 4 |             |
| 2 | 5 |           1 |
+---+---+-------------+

Показывая в этом случае uniqueifier не использовал значения из удаленных строк.

Однако затем работает

DELETE FROM T 
WHERE Y IN (6,7)
WAITFOR DELAY '00:00:10'
INSERT INTO T VALUES (1),(1)

дает

+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 |             |
| 1 | 8 |           1 |
| 1 | 9 |           2 |
| 2 | 4 |             |
| 2 | 5 |           1 |
+---+---+-------------+

Показывает, что верхняя отметка может быть сброшена после удаления дубликата с наибольшим значением уникализатора. Задержка состояла в том, чтобы разрешить запуск процесса очистки записи-призрака.

Поскольку жизнь слишком коротка, чтобы вставить 2 миллиарда дубликатов, я использовал DBCC WRITEPAGEручную настройку максимального значения uniqueifierдо 2 147 483 644.

введите описание изображения здесь

Я тогда побежал

INSERT INTO T VALUES (1)

многократно. Это удалось дважды и не удалось с третьей попытки с ошибкой 666.

Это было на самом деле на один ниже, чем я бы предположил. Это означает, что максимальный вставленный уникализатор был 2 147 483 646, а не максимальный размер int 2 147 483 647


В информационных целях вы можете проверить, TRUNCATE TABLEсбрасывает ли уникализатор?
Джон Зигель

@JonSeigel - Да, похоже. После запуска INSERT INTO T VALUES (1),(1),(1),(2),(2);TRUNCATE TABLE T;INSERT INTO T VALUES (1),(1),(1),(2),(2)самый высокий уникальный идентификатор, 2 я полагаю, смотрит на самый высокий уникальный идентификатор, который уже существует для этого ключа (включая записи о привидениях)
Martin Smith
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.