'Büyük' ​​veritabanı tablosu PK için sıralı GUID veya bigint


14

Bu tür bir sorunun çok geldiğini biliyorum, ama henüz bu kararı vermeme yardımcı olacak herhangi bir zorlayıcı argüman okumadım. Lütfen bana eşlik et!

Büyük bir veritabanım var - günde yaklaşık 10.000.000 kayıt büyüyor. Veriler ilişkiseldir ve performans nedenleriyle tabloyu BULK COPY ile yüklüyorum. Bu nedenle, satırlar için anahtarlar oluşturmak gerekir ve bir kimlik sütununa güvenemezsiniz.

64 bitlik bir tam sayı - bir bigint - kullanmam için yeterince geniş, ancak benzersizliği garanti etmek için, kimliklerimi benim için yapmak için merkezi bir jeneratöre ihtiyacım var. Şu anda bir servisin X sıra numaralarını ayırmasına izin veren ve çarpışmayı garanti etmeyen bir jeneratör servisim var. Bununla birlikte, bunun bir sonucu, sahip olduğum tüm hizmetlerin bu tek bir merkezi jeneratöre bağımlı olması ve bu yüzden sistemimi nasıl dağıtabileceğim konusunda kısıtlıyım ve uygulanan diğer bağımlılıklardan (ağ erişimi gerektirme gibi) memnun değilim bu tasarım ile. Bu bazen bir sorun oldu.

Şimdi sıralı GUID'leri birincil anahtarları (harici SQL için oluşturulan) olarak kullanmayı düşünüyorum. Kendi testlerimden emin olabildiğim kadarıyla, bunların tek dezavantajı, daha geniş bir veri türünün (dizinlerde kullanımıyla daha da kötüleşen) disk alanı ek yüküdür. Bigint alternatifine kıyasla sorgu performansında fark edilebilir bir yavaşlamaya tanık olmadım. Tabloyu BULK COPY ile yüklemek biraz daha yavaştır, ancak çok fazla değildir. Sıralı GUID uygulamam sayesinde GUID tabanlı dizinlerim parçalanmıyor.

Temel olarak, bilmek istediğim, göz ardı edebileceğim başka hususlar varsa. Şu anda, sıçramaya ve GUID'leri kullanmaya başlamaya meyilliyim. Ben kesinlikle bir veritabanı uzmanı değilim, bu yüzden gerçekten herhangi bir rehberlik takdir ediyorum.


2
"Sıralı bir GUID" nasıl oluşturulur?

Bu özel bir uygulama. Temel olarak, zaman damgası baytlarıyla değiştirilen 6 bayt ve zaman damgasının aynı olduğu bir sıra numarasını temsil eden 2 bayt içeren bir GUID türü biçimdir. Mükemmel ardışık değerler üretilmesi garanti edilmez, ancak dizin parçalanmasını benim için bir sorun haline getirecek kadar iyidir.

Bu nedenle bu verileri birden çok farklı kaynaktan mı yüklüyorsunuz? Ben de parçalanma konusunda endişe endeks kümelenmiş dizin olduğunu varsayalım?

2
Sıralı bir GUID ile gidiyorsanız, NEWSEQUENTIALID () öğesine bakmalısınız. İstediğinizi yapmalıdır (monoton olarak artar) ve özel koda dayanmaz.

2
Jeremiah Peschka mesajına bakın Tuşlarla ilgili sorun İyi okuyun ve bu uygulama ile birçok kez ilgilenir.
billinkc

Yanıtlar:


4

Ben de benzer bir durumdayım. Şu anda, sıralı GUID yaklaşımını kullanıyorum ve parçalanma ve kolay anahtar üretimi yok.

Bigint'e geçmeye başlamama neden olan iki dezavantajı fark ettim:

  1. Alan kullanımı . İndeks başına 8 bayt daha. Bunu 10 dizinle çarpın ve büyük bir alan israfı elde edin.
  2. Sütun deposu dizinleri GUID'leri desteklemez.

(2) Katil benim içindi.

Şimdi anahtarlarımı şu şekilde üreteceğim:

yyMMddHH1234567890

Bir öncü tarih artı saat kullanacağım ve bundan sonra sıralı bir bölüme sahip olacağım . Bu, herhangi bir ekleme endeksi olmadan verilerimi tarihe göre aralamamı sağlıyor. Bu benim için güzel bir bonus.

Bigint'in ardışık kısmını, dağıtılmasına iyi bir HiLo algoritması kullanarak oluşturacağım .

Umarım bunların bir kısmı sizin durumunuza geçer. Kesinlikle bigint kullanmanızı öneririz.


1
Bunu 'cevap' olarak işaretlemek, en uygun olanıdır (ve ne istediğimi ve bunun neden ilk göründüğü kadar basit olmadığını takdir ediyorsunuz). Sanırım (HiLo algoritma önerisine benzer şekilde çalışacak) paylaşılan bir sıra üreteci ile gideceğim. Bu, birkaç problemi olan başka bir sistem üzerinde çalışıyor, sadece ekstra bağımlılığa katlanmak zorundayım. Oh iyi. Teşekkürler.
Barguast

3

Bir türüyle INT, 1'den başlayan almak 2 milyar üzerinde vakaların büyük çoğunluğundan fazla yeterli olmalıdır - olası satırları. Ile BIGINT, yaklaşık 922 katrilyon olsun (15 sıfır ile 922 - 922'000 milyar) - sizin için yeterli ??

INT IDENTITY1'de bir başlangıç kullanırsanız ve her saniyede bir satır eklerseniz , 2 milyar sınırına ulaşmadan önce 66,5 yıl gerekir.

BIGINT IDENTITY1'de bir başlangıç kullanırsanız ve her saniyede bin satır eklerseniz , 922 katrilyon sınırına ulaşmadan önce 292 milyon yıl boyunca akıllara durgunluk veren bir miktara ihtiyacınız vardır ....

Günde 10 milyon satırınızı kullanarak , yaklaşık 1'844'674'407'370 gün ( 1844 milyar gün veya 5 milyar yıldan fazla bir kene ) veri için yeterli sayıya sahip olmanızı sağlar - ihtiyaçlarınız için yeterince iyi ?

MSDN Books Online'da bunun hakkında daha fazla bilgi edinin (tüm seçeneklerle birlikte) .


1
Günde 10 milyon satır ekleme oranı, INT aralığını 200 gün içinde tüketecektir.
mceda

@mceda: evet - başka bir şey talep ettim mi? Ancak, BIGINTaralığı hızla
tüketmez

Teşekkürler, ama sorumda dediğim gibi, veritabanına gönderilmeden önce kimliklere ihtiyacım var. Veri ilişkisel, bu yüzden toplu kopyalanmadan önce birincil ve yabancı anahtarlar atamak gerekir. Eğer böyle olmasaydı, KİMLİK BÜYÜKLÜĞÜ muhtemelen mükemmel olurdu.

2
@ Barguast: Verilerinizi bir hazırlama tablosuna (kimlik olmadan) toplu olarak ekleyip kullanarak gerçek veri tablolarınıza oradan taşıyamadınız BIGINT IDENTITYmı?
marc_s

@marc_s: evet, sağlanan hesaplama şu soru ile uyumlu değildi: "1'den başlayan bir INT IDENTITY kullanıyorsanız ve her saniyede bir satır eklerseniz, 2 milyar sınırına ulaşmadan önce 66,5 yıl gerekir".
mceda

2

Önbellek / nocache gibi seçeneklerle KİMLİK BÜYÜK veri türü SEQUENCE kullanmanızı öneriyoruz. Bu, küme / nocache gibi seçeneklerle KİMLİK'ten çok daha esnektir, ayrıca toplu işleminiz için sp_sequence_get_range olarak bir dizi aralığı atayabilirsiniz.


Maalesef SEQENCE Sql Azure'da desteklenmiyor.
Timothy Lee Russell

2

Yüklediğiniz ayrı tablolar arasında zaten yabancı anahtar ilişkileri olduğundan KİMLİK'i kullanamamanızın nedeni mi? Ve onları bir evrelendirme alanından üretim alanına bağlayabilmeniz için başka bir doğal anahtar yoktur? Bu nedenle, toplu kopyalamadan önce kaynak sistemde şu anda nasıl "bağlı" oldukları hakkında biraz daha bilgi edinmek ister misiniz? Birden çok kaynak sistem yalnızca kendi dizilerini kullanıyor mu ve paylaşılan bir veritabanına getirildiğinde çakışan diziler için olanaklı mı?

COMB ID / sıralı GUID tekniği, aşina olduğum bir tekniktir ve veritabanının dışında atanan küresel benzersizliğe etkili bir şekilde ihtiyaç duyduğunuzda uygulanabilir - veritabanının içinde ve dışında etkili bir satır kimliği. Bu nedenle, oldukça dağıtılmış ortamlarda veya bağlantısız senaryolarda, bu TAMAM bir seçimdir

Dışında veri boyutu büyüdükçe ve bu anahtarların her indeksi ve sorgular bir sürü için çalışan setleri olduğunda ekstra genişlik farkı önemli olduğu için gerçekten, gerek yoksa.

Ayrıca, dağıtılmış nesil ile, satırlar gerçekten GUID sütunu sırasına göre gelmezse, bunu kümelenmiş dizin anahtarı (dar, statik, artan) için kullanmayla ilgili sorunlar, hala bir KİMLİK'teki kümelemeye kıyasla parçalanmaya neden olabilir kalmak.


0

Genel olarak, verilerin her iki tabloya eklenmesi ve kimlik alanı ile ilgili olması için komut OUTPUTmaddesini kullanmak mümkündür INSERT.

Zaman damgasına dayanan tanımlayıcı güvenilir olarak düşünülmemelidir - donanım saatinden zaman senkronizasyon hizmetlerine kadar birçok şeye bağlı olan sistem saatine bağlıdır.

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.