MSG 666 al ejecutar una consulta de inserción en una tabla indexada de 80 millones de filas


10

Curiosamente, mi procedimiento almacenado comenzó a recibir Msg 666 para algunos datos de entrada.

El procedimiento almacenado falla en el último paso cuando intenta insertar una fila en una tabla con la siguiente estructura:

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

Esta es esencialmente una tabla que conecta todas las entidades referenciadas juntas.

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)

La fragmentación para ambos índices es baja (<25%). Sin embargo, la fragmentación PK_TableName crece rápidamente, ya que la cantidad de operación en la tabla es bastante intensa.

Tamaño de la mesa:

Row count: ~80,000,000 rows

Entonces, cuando intento ejecutar una consulta muy simple, para algunos de los D_Id aparece el siguiente mensaje:

Mensaje 666. Se excedió el valor único generado por el sistema máximo para un grupo duplicado para el índice con el ID de partición 422223771074560. Soltar y volver a crear el índice puede resolver esto; de lo contrario, use otra clave de agrupación.

Ejemplo de consulta:

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

Por ejemplo, cuando configuro D_Id en algunos valores, falla, por ejemplo, '14'. Si configuro D_ID a otros valores (1,2,3, ... 13, 15,16, ...), la consulta funciona bien.

Sospecho que hay algo realmente malo con los índices ... Pero no puedo llegar al fondo de esto ... :( ¿Por qué falla?

Respuestas:


16

El problema de baja selectividad mencionado por Remus no es suficiente por sí solo para causar el problema en esa tabla de tamaños.

El unificador comienza en 1y puede subir 2,147,483,646antes de desbordar el rango.

También requiere el patrón correcto de eliminaciones e inserciones repetidas para ver el problema.

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)

Da

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

Entonces corriendo

DELETE FROM T 
WHERE Y IN (2,3)

INSERT INTO T VALUES (1),(1)

Da

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

Mostrando en ese caso el unificador no reutilizó los valores de las filas eliminadas.

Sin embargo luego corriendo

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

Da

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

Mostrar que la marca de límite superior se puede restablecer después de eliminar el duplicado con el valor de unificador más alto El retraso fue permitir que se ejecutara el proceso de limpieza del registro fantasma.

Como la vida es demasiado corta para insertar 2 mil millones de duplicados, solía DBCC WRITEPAGEajustar manualmente la más alta uniqueifiera 2,147,483,644

ingrese la descripción de la imagen aquí

Entonces corrí

INSERT INTO T VALUES (1)

varias veces. Tuvo éxito dos veces y falló en el tercer intento con el error 666.

Este fue en realidad uno más bajo de lo que hubiera supuesto. Lo que significa que el unificador más alto insertado fue 2,147,483,646 en lugar del tamaño int máximo de 2,147,483,647


Con fines informativos, ¿puede verificar si TRUNCATE TABLErestablece el unificador?
Jon Seigel

@ JonSeigel - Sí, parece que sí. Después de ejecutar INSERT INTO T VALUES (1),(1),(1),(2),(2);TRUNCATE TABLE T;INSERT INTO T VALUES (1),(1),(1),(2),(2), el unificador más alto es 2 Supongo que mira el unificador más alto que ya existe para esa clave (incluidos los registros de fantasmas)
Martin Smith
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.