Yalnızca PK amaçları için bir çapraz referans tablosuna otomatik artış / KİMLİK alanı eklemeli miyim?


9

SQL Server tarafından barındırılan DB için aşağıdaki çapraz başvuru tablosu ekliyorum:

company_id bigint not null (FK)
org_path nvarchar (2048) not null

company_idAlan anlamına gelir idbaşka bir tabloda alan (ki burada birincil anahtar).

Aynı ile birden fazla kayıt olabileceği göz önüne alındığında company_id, herhangi bir birincil anahtarın her iki alanı da kullanması gerekir. Ancak, org_pathSQL Server için çok uzun olduğu için her iki alanı kullanarak bir anahtar oluşturamıyorum .

Gelince org_path, bu var olduğu tek tablo. Bu tablodaki sorguların tüm girişleri veya org_pathtarafından yapılan tüm girişleri istemesi olasılığı vardır company_id. Ya da başka bir deyişle, bu tablonun sorgulanacağı şüpheli görünüyor org_path. Ayrıca, org_pathgüncellenmesi ve daha fazla yerleştirilmesi ve - muhtemelen nadiren - silinmesi olası değildir .

Toplam satır sayısının düşük binlerde olmasını bekliyorum.

Ayrıca, bunun nedeni nvarchar (2048), değerin üçüncü taraf bir DB'de bunu taklit etmesi gerektiğidir. Tipik bir örnek,

\Translation Providers\[customer name]\[order name]\

ve aksan içerebilir.

Benim sorum şu: bir otomatik artış idalanı eklemek ve bunu company_idbirincil anahtar olarak kullanmak daha verimli olur mu yoksa gereksiz ek yükü ekler mi - ve company_idbaşka bir tabloda birincil anahtar olan herhangi bir etkisi?

Yanıtlar:


7

comany_idTek başına benzersiz olmayan bir kümelenmiş dizin için , SQL Server benzersiz hale getirmek için otomatik olarak tüm yinelenen (yani bir anahtar değeri için ikinci ve daha sonra) kümelenmiş dizin anahtarlarına 4 baytlık bir tam sayı benzersizleştiricisi ekler. Bu kullanıcıya maruz kalmaz.

İkincil anahtar sütunu olarak kendi benzersiz tanımlayıcınızı eklemenin avantajı, daha sonra yine company_idde daha verimli bir şekilde arama yapabilmenizdir (ayrıca kalıcı bir yüklemle kullanmak company_id, identitycolyerine ). Kümelenmiş dizin daha sonra benzersiz olur , bu nedenle gizli benzersizleştiriciler eklenmez.company_idorg_pathcompany_id, identitycol

Ayrıca, için yinelenen sonuçlarla karşılaşırsanız (company_id,org_path), açık kimlik sütununa (bir tür "açıklayıcı benzersizleştirici") sahip olmak, silmek veya güncellemek için bunlardan yalnızca birini hedeflemeyi kolaylaştırır.


12

Dikkate alınması gereken bir şey, Birincil Anahtar ve Kümelenmiş Bir Dizinin aynı şey olmadığıdır. Birincil Anahtar bir kısıttır ve verinin yaşadığı kurallarla (yani veri bütünlüğü) ilgilenir; verimlilik / performans ile ilgisi yoktur. Birincil Anahtar, anahtar sütun (lar) ın benzersiz (kombinasyon halinde) ve NOT NULL (ayrı ayrı) olmasını gerektirir. PK, Kümelenmiş veya Kümelenmemiş olabilmesine rağmen, Benzersiz bir Dizin yoluyla uygulanır.

Kümelenmiş Dizin, tablodaki verileri fiziksel olarak (yani diskte) sıralamak ve performansla ilgilenmek için kullanılan bir araçtır; veri bütünlüğü ile ilgisi yoktur. Bir kümelenmiş dizin kutuanahtar sütun (lar) ın benzersiz (birlikte) olmasını gerektirir, ancak buna gerek yoktur. Ancak, Kümelenmiş Dizin verilerin fiziksel sırası olduğundan, ne olursa olsun, her satırı benzersiz bir şekilde tanımlaması gerekir. Bu nedenle, benzersiz olmasını gerektirecek şekilde ayarlamazsanız, gizli 4 baytlık "benzersiz" sütun aracılığıyla kendi benzersizliğini oluşturur. Bu sütun, Benzersiz Kümelenmemiş Dizinlerde her zaman oradadır, ancak anahtar alanlar benzersiz olduğunda (birlikte) yer kaplamaz. Bu "benzersiz" sütunun nasıl çalıştığını ilk elden görmek için (hem Kümelenmiş Dizin'de hem de Kümelenmemiş Dizinler üzerindeki etki), Uniquifier boyutunu test etmek için PasteBin : T-SQL komut dosyasına gönderdiğim bu test komut dosyasına bakın .

Bu nedenle, ana soru:

bir otomatik artış idalanı company_ideklemek ve bunu birincil anahtar olarak birlikte kullanmak daha verimli olur mu yoksa gereksiz ek yük ekler mi

bu iki kavramı birleştiriyor, bu yüzden ayrı ayrı ele alınması gerekiyor, ancak kesinlikle bir çakışma var.

Bir IDENTITYsütun eklenmeli mi yoksa gereksiz ek yük mü olurdu?

Bir INT IDENTITYsütun ekleyip bir PK oluşturmak için kullanırsanız, her satıra 4 bayt ekleyen bir Kümelenmiş PK olacağını varsayarsak. Bu sütun sorgularda görülebilir ve kullanılabilir. Bu olabilir gerçi olmayacak bu özel durumda, bir yabancı anahtar olarak diğer tablolara eklenecektir.

INT IDENTITYSütunu eklemezseniz, bu tabloda bir PK oluşturamazsınız. Ancak, seçeneği kullanmadığınız sürece yine de bir Kümelenmiş Dizin oluşturabilirsiniz UNIQUE. Bu durumda, SQL Server yukarıda açıklandığı gibi davranan "benzersiz" adlı gizli bir sütun ekleyecektir. Sütun gizlendiğinden, sorgularda veya Yabancı Anahtarlar için başvuru olarak kullanılamaz.

Verimlilik söz konusu olduğunda, bu seçenekler kabaca aynıdır. Evet, bazı satırların (ilk benzersiz anahtar değerlerine sahip olanlar) 0 bayt alması nedeniyle Benzersiz Kümelenmemiş Endeks'in 0 bayt alması nedeniyle biraz daha az yer kaplar, IDENTITY/ PK'daki tüm satırlar 4 bayt alır. Ancak, 0 baytlık satırlardan (özellikle beklenen az miktarda satırla), IDsütunu sorgularda kullanabilmenin rahatlığını daha da fazla bırakmak yerine, bir fark fark etmek için yeterli olmayacaktır .

INT IDENTITY sütunu mu yoksa org_pathkalıcı hesaplanmış sütun karma ?

org_pathDeğerlere dayalı satırlara bakmayacağınız göz önüne alındığında , Kalıcı Hesaplanmış Sütun ek yükünü ve Hesaplanmış Sütunla eşleşmek için sorgulardaki bu karma değerini hesaplamanız gerekir. Buradaki revizyon geçmişinde mevcut olan orijinal öneri, Sorunun ilk ifadesine / ayrıntılarına dayanmaktadır). Bu özel durumda, INT IDENTITY"ID" Sütunu muhtemelen en iyisidir.

Anahtar Sütun Sırası

Düşünüldüğünde IDKolon nadiren, if ever, sorgularda kullanılan, olacak ve iki ana kullanımın söz ya "tüm satırları" veya "belirli bir için tüm satırları almak olduğu göz önüne alındığında company_id," Ben PK yaratacak company_id, id. Ve bu, satırların sırayla eklenmediği için FILLFACTOR, 90 değerini belirtirim . Parçalamayı azaltmak için düzenli dizin bakımı yaptığınızdan da emin olmanız gerekir.

İkinci soru

company_id'in başka bir tablodaki birincil anahtar olması, burada herhangi bir etkiye sahip mi?

Hayır.

tetik

A org_pathiçindeki değerler company_idbenzersiz olduğundan, bunu INSERT, UPDATEuygulamak için yine de bir Tetikleyici oluşturmanız gerekir . Tetikleyicide, IF EXISTSmuhtemelen bir COUNT(*)ve yapan bir sorgu ile bir yapın GROUP BY company_id, org_path. Bir şey bulunursa, ROLLBACKDML işlemini iptal etmek için a ve ardından RAISERRORyinelemeler olduğunu söyleyerek sorun yaşayın .

karşılaştırma

İlk cevabımda (sorunun orijinal ifadelerine / seyrek ayrıntılarına dayanarak ve burada düzeltme geçmişinde mevcut ), muhtemelen bir ikili (yani _BIN2) Harmanlama kullanmanızı önermiştim . Şimdi tam olarak ne içgörü olması org_path, ben ederim değil bir ikili harmanlama kullanılması önerilir. Ayırıcı işaretler söz konusu olacağı için, sen do dilsel eşdeğerlik faydalanmak istiyoruz.



0

Neden bir PK'ye ihtiyacınız var?

Neden yalnızca kümelenmemiş bir dizin olarak company_id ile gitmiyorsunuz?

En çok arananların tüm kayıtlarda veya şirket_kimliği ile olduğunu söylediniz
Nadiren güncelleme
Nadiren
org_path'i silin , bu var olduğu tek tablo

Martin Smith'in cevabı size ihtiyacınız olan
şeyi alabilir Otomatik olarak 4 baytlık tamsayı benzersizleştirici eklemeye aşina değilim
Belki bir şey eksik ama dizinlenmiş başka sütunlarınız yoksa, bu kullanım durumunda bunun için bir amaç görmüyorum

DRI ile ilgili endişeleriniz varsa tablolar Company_id için FK olarak Şirket tablosunu kullanmalıdır


Hey. "İlgili Neden sadece olmayan bir kümelenmiş dizini olarak company_id ile gitmez? ": Yani 2 aşağı tarafı olurdu çünkü: 1) bir kümelenmiş dizin oysa 1 şey daha yer kaplıyor olacak olan tablo hiçbir ek öğe böylece, ve 2) bir INCLUDEsütun olmadıkça NVARCHAR alanını elde etmek için bir RID araması gerektirir , ancak bu yalnızca tabloyu çoğalttığından daha da kötüdür. Doğru, PK gerekli değildir; önemli kısmı Kümelenmiş Endeks'tir. Ama bir kez KİMLİĞİNİZ varsa, PK ile de gidebilirsiniz. Ve lütfen Uniquifier walk
Solomon Rutzky

@srutzky Ama bir 4 bayt tam sayı benzersizleştiriciden kaçınır, bu yüzden bunu bir yıkama olarak görüyorum
paparazzo

10k satırdan daha azıyla, önemli olmayacak; sadece 4 baytın etkisini fark etmeden önce muhtemelen milyonlarca satırda olmanız gerekir. Dolayısıyla, "Tüm satırları al" sorgusu için bu seçeneklerin hiçbirinde gerçekten bir fark yoktur. Ancak "get for company_id = @param" sorgusu için, fiziksel olarak company_id tarafından sipariş edilen verilere sahip olmak, özellikle de her satır için bir RID araması yapması gerekmediğinde yardımcı olacaktır.
Solomon Rutzky

@srutzky Yıkama bir yıkama - 10K veya 1G. Bu sadece OP'nin dikkate alması gereken bir şey.
paparazzo
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.