MSG 666 khi chạy truy vấn chèn trên bảng được lập chỉ mục 80M hàng


10

Thật kỳ lạ, quy trình được lưu trữ của tôi bắt đầu nhận Msg 666 cho một số dữ liệu đầu vào.

Thủ tục lưu trữ không thành công ở bước cuối cùng khi nó cố gắng chèn một hàng vào bảng có cấu trúc sau:

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

Đây thực chất là một bảng kết nối tất cả các thực thể được tham chiếu với nhau.

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)

Phân mảnh cho cả hai chỉ số thấp (<25%). Tuy nhiên, phân mảnh PK_TableName nhanh chóng phát triển, vì số lượng hoạt động trên bàn khá dữ dội.

Kích thước bảng:

Row count: ~80,000,000 rows

Vì vậy, khi tôi cố gắng chạy một truy vấn đơn giản,, đối với một số D_Id, tôi nhận được thông báo sau:

Msg 666. Giá trị duy nhất do hệ thống tạo tối đa cho một nhóm trùng lặp đã bị vượt quá đối với chỉ mục với ID phân vùng 422223771074560. Việc thả và tạo lại chỉ mục có thể giải quyết điều này; mặt khác, sử dụng một khóa phân cụm khác.

Ví dụ truy vấn:

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

Ví dụ: khi tôi đặt D_Id thành một số giá trị - chẳng hạn, '14'. Nếu tôi đặt D_ID thành các giá trị khác (1,2,3, ... 13, 15,16, ...), truy vấn sẽ chạy tốt.

Tôi nghi ngờ có điều gì đó thực sự tồi tệ xảy ra với các chỉ mục ... Nhưng tôi không thể đi đến tận cùng của điều này ... :( Tại sao nó thất bại?

Câu trả lời:


16

Vấn đề chọn lọc thấp được Remus đề cập là không đủ để gây ra sự cố trên bảng kích thước đó.

Trình duy nhất bắt đầu tại 1và có thể đi lên 2,147,483,646trước khi thực sự vượt quá phạm vi.

Nó cũng đòi hỏi mô hình đúng của các lần xóa và chèn lặp đi lặp lại để xem vấn đề.

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)

Tặng

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

Sau đó chạy

DELETE FROM T 
WHERE Y IN (2,3)

INSERT INTO T VALUES (1),(1)

Tặng

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

Hiển thị trong trường hợp đó, trình duy nhất không sử dụng lại các giá trị từ các hàng đã xóa.

Tuy nhiên sau đó chạy

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

Tặng

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

Cho thấy rằng dấu nước cao có thể được đặt lại sau khi xóa bản sao có giá trị duy nhất cao nhất. Sự chậm trễ là cho phép quá trình dọn dẹp hồ sơ ma chạy.

Vì cuộc sống quá ngắn để chèn 2 tỷ bản sao, sau đó tôi đã sử dụng DBCC WRITEPAGEđể điều chỉnh thủ công mức cao nhất uniqueifierthành 2.147.483.644

nhập mô tả hình ảnh ở đây

Sau đó tôi chạy

INSERT INTO T VALUES (1)

nhiều lần. Nó đã thành công hai lần và thất bại ở lần thử thứ ba với lỗi 666.

Đây thực sự là một mức thấp hơn tôi nghĩ. Có nghĩa là công cụ duy nhất cao nhất được chèn là 2.147.483.646 chứ không phải kích thước int tối đa là 2.147.483.647


Đối với mục đích thông tin, bạn có thể kiểm tra nếu TRUNCATE TABLEđặt lại bộ duy nhất không?
Jon Seigel

@JonSeigel - Vâng, dường như. Sau khi chạy INSERT INTO T VALUES (1),(1),(1),(2),(2);TRUNCATE TABLE T;INSERT INTO T VALUES (1),(1),(1),(2),(2)thì công cụ duy nhất cao nhất là 2 tôi cho rằng nó nhìn vào công cụ duy nhất cao nhất đã tồn tại cho khóa đó (bao gồm các bản ghi ma)
Martin Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.