Igo*_*lin 10 index sql-server-2008 sql-server
奇怪的是,我的存储过程开始收到一些输入数据的消息 666。
存储过程在最后一步尝试将行插入具有以下结构的表时失败:
Columns:
A_Id: PK, int
B_Id: PK, FK, int
C_Id: PK, FK, int
D_Id: PK, smallint
Run Code Online (Sandbox Code Playgroud)
这本质上是一个将所有引用实体连接在一起的表。
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)
Run Code Online (Sandbox Code Playgroud)
两个索引的碎片化程度都很低 (<25%)。然而 PK_TableName 碎片迅速增长,因为对表的操作量非常大。
桌子尺寸:
Row count: ~80,000,000 rows
Run Code Online (Sandbox Code Playgroud)
因此,当我尝试运行一个简单的查询时,对于某些 D_Id,我收到以下消息:
消息 666。对于分区 ID 为 422223771074560 的索引,已超出系统为重复组生成的最大唯一值。删除并重新创建索引可能会解决此问题;否则,使用另一个聚类键。
查询示例:
INSERT INTO TableName
(A_Id,B_Id,C_Id,D_id)
VALUES (1,1,1,14)
Run Code Online (Sandbox Code Playgroud)
例如,当我将 D_Id 设置为某些值时 - 它失败,例如“14”。如果我将 D_ID 设置为其他值 (1,2,3,...13, 15,16,...),则查询运行良好。
我怀疑索引有一些非常糟糕的事情......但我无法深入了解...... :(为什么它会失败?
Mar*_*ith 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)
Run Code Online (Sandbox Code Playgroud)
给
+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 | |
| 1 | 2 | 1 |
| 1 | 3 | 2 |
| 2 | 4 | |
| 2 | 5 | 1 |
+---+---+-------------+
Run Code Online (Sandbox Code Playgroud)
然后运行
DELETE FROM T
WHERE Y IN (2,3)
INSERT INTO T VALUES (1),(1)
Run Code Online (Sandbox Code Playgroud)
给
+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 | |
| 1 | 6 | 3 |
| 1 | 7 | 4 |
| 2 | 4 | |
| 2 | 5 | 1 |
+---+---+-------------+
Run Code Online (Sandbox Code Playgroud)
在这种情况下显示唯一标识符没有重用已删除行中的值。
但是然后运行
DELETE FROM T
WHERE Y IN (6,7)
WAITFOR DELAY '00:00:10'
INSERT INTO T VALUES (1),(1)
Run Code Online (Sandbox Code Playgroud)
给
+---+---+-------------+
| X | Y | Uniqueifier |
+---+---+-------------+
| 1 | 1 | |
| 1 | 8 | 1 |
| 1 | 9 | 2 |
| 2 | 4 | |
| 2 | 5 | 1 |
+---+---+-------------+
Run Code Online (Sandbox Code Playgroud)
显示删除具有最高唯一值的重复项后可以重置高水位标记。延迟是为了允许幽灵记录清理过程运行。
因为寿命太短,无法插入 20 亿个重复项,然后我使用DBCC WRITEPAGE手动将最高值调整uniqueifier为 2,147,483,644

然后我跑了
INSERT INTO T VALUES (1)
Run Code Online (Sandbox Code Playgroud)
多次。它成功了两次,第三次尝试失败,出现错误 666。
这实际上比我想象的要低。这意味着插入的最高唯一标识符是 2,147,483,646 而不是最大的 int 大小 2,147,483,647
| 归档时间: |
|
| 查看次数: |
2094 次 |
| 最近记录: |