MSG 666 quando si esegue una query di inserimento su una tabella indicizzata a 80 M di righe


10

Stranamente, la mia procedura memorizzata ha iniziato a ricevere il messaggio 666 per alcuni dati di input.

La procedura memorizzata non riesce nell'ultimo passaggio quando tenta di inserire una riga in una tabella con la seguente struttura:

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

Questa è essenzialmente una tabella che collega insieme tutte le entità referenziate.

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 frammentazione per entrambi gli indici è bassa (<25%). Tuttavia, la frammentazione di PK_TableName aumenta rapidamente, poiché la quantità di operazioni sulla tabella è piuttosto intensa.

Dimensioni della tavola:

Row count: ~80,000,000 rows

Quindi, quando provo a eseguire una semplice query veeery, per alcuni dei D_Id ricevo il seguente messaggio:

Messaggio 666. Il valore univoco massimo generato dal sistema per un gruppo duplicato è stato superato per l'indice con ID partizione 422223771074560. Eliminare e ricreare l'indice può risolvere questo problema; in caso contrario, utilizzare un'altra chiave di clustering.

Esempio di query:

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

Ad esempio, quando imposto D_Id su alcuni valori, non riesce, ad esempio "14". Se imposto D_ID su altri valori (1,2,3, ... 13, 15,16, ...), la query funziona correttamente.

Ho il sospetto che stia succedendo qualcosa di veramente brutto con gli indici ... Ma non riesco ad arrivare in fondo a questo ... :( Perché fallisce?

Risposte:


16

Il problema della bassa selettività menzionato da Remus non è di per sé sufficiente a causare il problema su quella tabella di dimensioni.

L'unicatorizzatore inizia da 1e può salire fino a 2,147,483,646traboccare effettivamente l'intervallo.

Richiede anche il giusto modello di ripetute cancellazioni e inserti per vedere il 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)

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

Quindi correndo

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 |
+---+---+-------------+

Mostrando in tal caso l'unicator non ha riutilizzato i valori dalle righe eliminate.

Tuttavia, quindi in esecuzione

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 |
+---+---+-------------+

Mostrando che è possibile reimpostare il contrassegno di acqua alta dopo aver eliminato il duplicato con il valore univoco più alto. Il ritardo era consentire l'esecuzione del processo di pulizia dei record fantasma.

Dato che la vita è troppo breve per inserire 2 miliardi di duplicati, ho usato DBCC WRITEPAGEper regolare manualmente il massimo uniqueifiera 2.147.483.644

inserisci qui la descrizione dell'immagine

Allora ho corso

INSERT INTO T VALUES (1)

più volte. Ci riuscì due volte e fallì al terzo tentativo con errore 666.

Questo era in realtà uno inferiore a quanto avrei immaginato. Ciò significa che l'unicificatore più alto inserito era 2.147.483.646 anziché la dimensione int massima di 2.147.483.647


A scopo informativo, è possibile verificare se TRUNCATE TABLEreimposta l'unicificatore?
Jon Seigel,

@JonSeigel - Sì, sembra. Dopo aver eseguito, INSERT INTO T VALUES (1),(1),(1),(2),(2);TRUNCATE TABLE T;INSERT INTO T VALUES (1),(1),(1),(2),(2)allora l'unicificatore più alto è 2 presumo che guardi l'unicificatore più alto che esiste già per quella chiave (compresi i record fantasma)
Martin Smith,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.