IDENTITY sütununda beklenmeyen boşluklar


18

Ben 1 başlayan ve 1 ile artış benzersiz satınalma siparişi sayıları oluşturmak çalışıyorum. Bu komut dosyası kullanılarak oluşturulan bir PONumber tablo var:

CREATE TABLE [dbo].[PONumbers]
(
  [PONumberPK] [int] IDENTITY(1,1) NOT NULL,
  [NewPONo] [bit] NOT NULL,
  [DateInserted] [datetime] NOT NULL DEFAULT GETDATE(),
  CONSTRAINT [PONumbersPK] PRIMARY KEY CLUSTERED ([PONumberPK] ASC)    
);

Ve bu komut dosyası kullanılarak oluşturulan saklı yordam:

CREATE PROCEDURE [dbo].[GetPONumber] 
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [dbo].[PONumbers]([NewPONo]) VALUES(1);
    SELECT SCOPE_IDENTITY() AS PONumber;
END

Yaratılış zamanında, bu iyi çalışıyor. Saklı yordam çalıştırıldığında, istenen sayıdan başlar ve 1 artar.

Garip olan şey, bilgisayarımı kapatır veya hazırda bekletirsem, işlem bir dahaki sefer çalıştığında, dizinin neredeyse 1000 oranında ilerlemesidir.

Aşağıdaki sonuçları görün:

PO Numaraları

Rakamın 8'den 1002'ye atladığını görebilirsiniz!

  • Bu neden oluyor?
  • Sayıların bu şekilde atlanmamasını nasıl sağlarım?
  • İhtiyacım olan tek şey SQL sayıları oluşturmak için:
    • a) Benzersiz garantili.
    • b) istenen miktarda artırılır.

SQL uzmanı olmadığımı itiraf ediyorum. SCOPE_IDENTITY () işlevinin ne yaptığını yanlış anlıyor muyum? Farklı bir yaklaşım mı kullanmalıyım? SQL 2012 ve sonraki sürümlerde dizilere baktım, ancak Microsoft varsayılan olarak benzersiz olmalarının garanti edilmediğini söylüyor.

Yanıtlar:


25

Bu bilinen ve beklenen bir sorundur - KİMLİK sütunlarının SQL Server tarafından yönetilme biçimi SQL Server 2012'de değişmiştir ( bazı arka plan ); varsayılan olarak 1000 değeri önbelleğe alır ve SQL Server'ı yeniden başlatırsanız, sunucuyu yeniden başlatırsanız, başarısız olur, vb. Veriliş. Bu burada belgelenmiştir . Bu davranışı, her IDENTITY atamasının günlüğe kaydedileceği şekilde * değiştiren bir izleme bayrağı vardır. Bununla birlikte, bunun performans açısından oldukça maliyetli olabileceğini belirtmek önemlidir, bu yüzden burada belirli izleme işaretinden bahsetmeyeceğim bile.

* (Şahsen, bunun farklı bir şekilde çözülebilecek teknik bir sorun olduğunu düşünüyorum, ancak motoru yazmadığım için bunu değiştiremiyorum.)

KİMLİK ve SEQUENCE'ın nasıl çalıştığı konusunda net olmak için:

  • İkisinin de benzersiz olduğu garanti edilmez (bunu birincil düzeyde veya benzersiz bir kısıtlama kullanarak tablo düzeyinde uygulamanız gerekir)
  • İkisinin de boşluksuz olması garanti edilmez (örneğin, herhangi bir geri dönüş veya silme bir boşluk üretecektir, buna rağmen bu özel sorun)

Benzersizliğin uygulanması kolaydır. Boşluklardan kaçınmak değildir. Bu boşluklardan kaçınmanın sizin için ne kadar önemli olduğunu belirlemelisiniz (teoride, IDENTITY / SEQUENCE değerleri anlamsız yedek anahtarlar olması gerektiğinden, boşlukları hiç önemsememelisiniz). Çok önemliyse, o zaman her iki uygulamayı da kullanmamalısınız, daha ziyade kendi serileştirilebilir sekans üretecinizi yuvarlayın ( burada , burada ve burada bazı fikirlere bakın ) - sadece eşzamanlılığı öldüreceğini unutmayın.

Bu "sorun" hakkında arka plan sürü:


Bu yanıt ("izleme bayrağı" bölümü hariç) diğer SQL veritabanlarının çoğu için de geçerlidir (yine de dizileri olanlar).
mustaccio

Cevap için teşekkürler. Teklik en önemli gereksinimdir. Boşluklar, büyük olmadıkları sürece büyük bir sorun değildir. örneğin 1'den 4'e gitmek kabul edilebilir, ancak 4'ten 1003'e kabul edilemez.
Ege Ersoz

1
Kısa versiyon: Kimlik değerleri satınalma siparişi numaraları olarak kullanılacaktır. Müşteri aylık raporlar çalıştırır ve yalnızca PO numarasına bakarak o ay kaç PO'nun gönderildiğini hızlı bir şekilde anlatmak ister. Bu yüzden ~ 1000 artırım yapamayız (DB sunucusu dahil tüm sunucuların yeniden başlatıldığı haftalık bakım var).
Ege Ersoz

3
Neden onlara sadece ROW_NUMBER () OVER (Aya göre PARTITION by ID ORDER BY ID) kullanan çok kolay bir rapor vermiyorsunuz? Yine, kimlik numarası anlamsız olmalı, kaç emir alındığını göz küresine götürmenin korkunç bir yoludur. Kodunuzda 1000 satırı silen veya 275 işlemi geri alan bir hata varsa veya 500 sipariş yasal olarak iptal edilirse ne olur?
Aaron Bertrand

1
@Ege: "... kaç kişiye söyle ... sadece PO numarasına bakarak". Kullanıcılarınız hayal kırıklığına uğrayacak. Kimlik değerleri bu şekilde çalışmaz ya da siz (ya da onlar) böyle bir varsayımda bulunmamalısınız. Benzersiz? Evet. Ardışık? Hayır. Bir ay içinde gönderilen PO'ları saymanın doğru yolu ... her bir kayıttaki bazı [değiştirilemez] Tarih alanına dayanarak o ay boyunca ortaya çıkan PO'ların sayısını saymaktır.
Phill W.

-4

Bu SQL Server sorunudur. Tek yapabileceğiniz sütun yeniden.

yanlış sütun kimliğine sahip girdileri silin. Sütun kimliğini yeniden boyutlandırın. Ve bir sonraki girişin kimliği doğru.

Aşağıdaki sql komutunu kullanarak kimliğinizi yeniden boyutlandırın: DBCC CHECKIDENT ('YOUR_TABLE_NAME', RESEED, 9)- 9 son doğru kimlik


1
"Girişleri sil" ile ne demek istiyorsun?
ypercubeᵀᴹ

2
Hmmm .. girişlerin silinmesi sadece veri kaybına yol açabilir.
Michael Green
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.