80M 행 인덱스 테이블에서 삽입 쿼리를 실행할 때 MSG 666


10

이상하게도 내 저장 프로 시저가 일부 입력 데이터에 대해 메시지 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

그래서 veeery simple query를 실행하려고하면 D_Id 중 일부에 대해 다음 메시지가 표시됩니다.

메시지 666. 파티션 ID가 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이 언급 한 낮은 선택성 문제만으로는 해당 크기 테이블에 문제를 일으킬 수 없습니다.

고유기는 실제로 범위를 오버플 12,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 |
+---+---+-------------+

이 경우 고유 식별자는 삭제 된 행의 값을 재사용하지 않았습니다.

그러나 그런 다음 실행

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

고유 번호 값이 가장 높은 복제본을 삭제 한 후 상위 워터 마크를 재설정 할 수 있음을 나타냅니다. 지연은 고스트 레코드 정리 프로세스를 실행하는 것이 었습니다.

수명이 20 억 장을 삽입하기에는 너무 짧기 때문에 DBCC WRITEPAGE수동으로 최고 값 uniqueifier을 2,147,483,644로 조정했습니다.

여기에 이미지 설명을 입력하십시오

나는 그 다음 달렸다

INSERT INTO T VALUES (1)

여러 번. 오류 666으로 세 번째 시도에서 두 번 성공했으며 실패했습니다.

이것은 실제로 내가 생각했던 것보다 하나 낮았습니다. 삽입 된 가장 높은 고유 식별자는 최대 int 크기가 2,147,483,647이 아니라 2,147,483,646이었습니다.


정보 제공을 위해 TRUNCATE TABLE고유자를 재설정 하는지 확인할 수 있습니까?
Jon Seigel

@ 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.