80M satırlı dizinlenmiş tabloda bir ekleme sorgusu çalıştırılırken MSG 666


10

Tuhaf bir şekilde, saklı yordam bazı girdi verileri için Msg 666 almaya başladı.

Aşağıdaki yapıya sahip bir tabloya satır eklemeye çalıştığında saklanan yordam son adımda başarısız olur:

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

Bu esasen referans alınan tüm varlıkları birbirine bağlayan bir tablodur.

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)

Her iki indeks için de parçalanma düşüktür (<% 25). Ancak PK_TableName parçalanması hızla büyür, çünkü masadaki işlem miktarı oldukça yoğundur.

Masa boyutu:

Row count: ~80,000,000 rows

Yani, bir veeery basit bir sorgu çalıştırmaya çalıştığınızda, bazı D_Id's için aşağıdaki iletiyi alıyorum:

Msg 666. 422223771074560 bölüm kimliğine sahip dizin için yinelenen bir grup için sistem tarafından oluşturulan benzersiz değer aşıldı. Dizinin düşürülmesi ve yeniden oluşturulması bu sorunu çözebilir; aksi halde başka bir kümeleme anahtarı kullanın.

Sorgu örneği:

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

Örneğin, bazı değerlere D_Id ayarladığımda - başarısız oluyor, örneğin '14'. D_ID değerini diğer değerlere (1,2,3, ... 13, 15,16, ...) ayarlarsam, sorgu düzgün çalışır.

Endekslerle ilgili gerçekten kötü bir şey olduğundan şüpheleniyorum ... Ama bunun altına inemiyorum ... :( Neden başarısız oluyor?

Yanıtlar:


16

Remus tarafından bahsedilen düşük seçicilik sorunu, bu boyut tablosunda soruna neden olmak için tek başına yeterli değildir.

Benzersizleştirici başlangıçta başlar 1ve 2,147,483,646aralığın gerçekte taşmasından önce yukarı çıkabilir .

Ayrıca, sorunu görmek için tekrarlanan silme ve eklerin doğru desenini gerektirir.

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)

verir

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

Sonra koşuyor

DELETE FROM T 
WHERE Y IN (2,3)

INSERT INTO T VALUES (1),(1)

verir

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

Bu durumda benzersizleştirici, silinen satırlardaki değerleri yeniden kullanmadı.

Ancak daha sonra

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

verir

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

En yüksek benzersiz değeri olan kopyayı sildikten sonra yüksek su işaretinin sıfırlanabileceğini gösterir. Gecikme, hayalet kaydı temizleme işleminin çalışmasına izin vermekti.

Hayat 2 milyar kopya eklemek için çok kısa olduğu için DBCC WRITEPAGE, en yüksek değeri uniqueifier2.147.483.644'e elle ayarlamak için kullandım .

resim açıklamasını buraya girin

Sonra koştum

INSERT INTO T VALUES (1)

bir kaç sefer. İki kez başarılı oldu ve üçüncü denemede 666 hatasıyla başarısız oldu.

Bu aslında sandığımdan daha düşüktü. Takılan en yüksek benzersizleştiricinin, maksimum int boyutu 2.147.483.647 yerine 2.147.483.646 olduğu anlamına gelir.


Bilgi amaçlı olarak, TRUNCATE TABLEbenzersizleştiricinin sıfırlanıp sıfırlanmadığını kontrol edebilir misiniz ?
Jon Seigel

@JonSeigel - Evet, öyle görünüyor. Çalıştırdıktan sonra INSERT INTO T VALUES (1),(1),(1),(2),(2);TRUNCATE TABLE T;INSERT INTO T VALUES (1),(1),(1),(2),(2)sonra en yüksek benzersizleştirici olduğunu 2 ben zaten (hayalet kayıtları dahil) bu anahtarın bulunduğu en yüksek benzersizleştirici bakar tahmin
Martin Smith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.