Bir veritabanı boyunca tek bir birincil anahtar dizisini mi paylaşıyorsunuz?


14

Tek bir diziyi tüm tablolarda birincil anahtar olarak kullanmak kabul edilebilir bir uygulama mıdır (bir birincil anahtar belirli bir tablo için benzersiz olmak yerine, tüm tablolar için benzersizdir)? Öyleyse objektif olarak tablolar arasında tek bir birincil anahtar dizisi kullanmaktan daha iyidir.

Ben bir DBA değil, küçük bir yazılım geliştiriciyim, bu yüzden hala iyi veritabanı tasarımının temellerini öğreniyorum.

Düzenleme: Herkes merak durumunda, ben son zamanlarda tasarım farklı bir kulağa farklı gelen tüm veritabanı boyunca tek bir birincil anahtar kullanmıyordu bir sorun olduğunu belirtti firmamızın DBA'larından biri tarafından bir veritabanı tasarımı eleştirisi okudum Şimdiye kadar öğrendim.

Edit2: yorumlarda bir soruya cevap, bu Oracle 11g için, ama ben veritabanına özgü olmayan bir düzeyde merak ediyordum. Bu soru veritabanına bağlıysa, nedenini bilmek isterdim, ancak böyle bir durumda Oracle'a özgü bir cevap arıyorum.


2
Performans nedeniyle genellikle korkunç bir fikirdir.
Philᵀᴹ

1
Aslında, her tablonun kendi bağımsız birincil anahtar aralığına sahip olmasının daha güçlü bir yararı vardır. Ancak sadece bir grup kimliğe baktığınızda, bu Hesaplar, bir Satın Alma Başlığı, vb. Bunu yapabilmeniz için bazı kurulumlar ve (herhangi bir özel amaçlı şey gibi) devam eden bakım ve besleme gerekir. (Evet, yıllar önce böyle bir sistemle çalıştım.)
RLF

Hangi DBMS'yi kullanıyorsunuz? Oracle? Postgres? DB2?
a_horse_with_no_name

1
Ne demek istediğini yanlış yorumlamanız mümkün mü? Belki de tam anlamıyla o değildi?
JamesRyan

Şirket DBA'sı aslında tabloların hiçbirinde birincil anahtar alan bulunmadığı anlamına mı geliyordu?
Max Vernon

Yanıtlar:


13

Kabul edilebilir? Elbette. Yaygın? Hayır. Yararlı mı? Şüpheli.

Eski işimde, merkezi bir dizi üretecine sahip oldukları bir sistemi miras aldık (bu, SEQUENCESQL Server 2012'de daha önce tanıtılan bir SQL Server sistemiydi ). Bu gerçekten bir performans darboğazı değildi ve saniyede yüz binlerce değer üretmediğiniz sürece olmamalıdır. Ancak, tüm kodu olması gerekenden çok daha karmaşık hale getirdi, iyi bir sebep yok. Tasarımın amacı, sistemdeki bir şeye 12 kimlik değeri atandığında, sistemdeki tek bir şeyin 12 numaralı kimliğe sahip olabileceğinden emin olmaktı. Bu benim için oldukça geniş görünüyordu ve bunu hiç anlamadım. CustomerID = 12 olan bir müşterim varsa, bu neden OrderID = 12 ile sipariş vermemi engelliyor?

Birden çok sisteminiz varsa ve bu birden çok sistemden belirli bir varlık türü (örneğin, bir müşteri veya sipariş) için kimlikler oluşturuyorsanız merkezi bir dizi oluşturucunun kullanışlılığını görüyorum. Merkezi bir dizi, bir darboğaz (sadece tek bir arıza noktası) olmadan ve aynı kimliği üreten iki sistemden korkmadan birden fazla sistem için yeni değerler yapabilir.


Böyle bir şey arasında seçim yapmak ve yalnızca benzersiz tanımlayıcıları birincil anahtarlar olarak kullanmak zorunda olsaydınız, bir tercihiniz olurdu (cevap büyük olasılıkla "duruma bağlıdır")? Bir GUID sorunla aynı şekilde çalışacak gibi görünüyor, ancak kendi merkezi birincil anahtar üretecinizi yuvarlamak yerine standart bir uygulama elde edersiniz. Açıkçası, SQL 2012'de bir dizi kullanmak her iki şeyi de başarırdı, ancak birisinin daha eski bir sürümde olduğu varsayılarak?
SqlRyan

2
@SqlRyan Bir OrderID'nin neden bir CustomerID'den tamamen farklı olması gerektiğini anlamam gerekir. Neredeyse kesinlikle bunun için bir GUID kullanmazdım; IDENTITY aralıklarını ayarlamak daha iyi olabilir (Müşteriler 1'den başlar, Siparişler 1000000'den başlar, vb.).
Aaron Bertrand

1
@SqlRyan - kümelenmiş birincil anahtar olarak kötü uygulanmış bir GUID kullanmak her türlü soruna neden olabilir. Aaron'un dediği gibi, IDENTITY amaca çok daha iyi uyuyor.
Max Vernon

Önceki bir sistemde, tüm veritabanı boyunca tek bir sıra kullandığımı gördüm, bu yabancı bir anahtarın tek bir tablo yerine çok sayıda farklı tabloya işaret etmesine izin vermek için yapıldı, böylece iki farklı satırın yabancı anahtarının 12 yaşındayken, hangi olası masaya işaret ettiklerini kontrol etmeden aynı şeyi gösterdiğini biliyordunuz. Aynı sütundaki 13, farklı bir tabloda birincil anahtar olabilir. Bu tasarım tarzından şahsen çok rahatsız oluyorum.
Lawtonfogle

@AaronBertrand Veya alternatif olarak basit tamsayı tanımlayıcıları kullanın ve bunlar müşteriye dönük olduğunda başlangıca bir miktar kod ekleyin. Örneğin. I1337, C1337 açıkça bir fatura veya müşteri
JamesRyan

7

Fikir, insanların yanlış sütunu kullanarak yanlışlıkla bir tabloya katılabilecekleri ve INT ID'leri aynı olduğu için geçersiz satırlar alabilecekleri çok karmaşık bir veritabanında değer taşıyor.

GUID'lerin bazı dizin parçalama tuzaklarından kaçınmak için birincil anahtarlarımız olarak sıralı GUID'leri seçtik. Ne yazık ki oldukça büyükler.

SQL sunucusu, varsayılan olarak newSequentialID () işlevini çağırarak sıralı GUID'ler oluşturabilir, böylece korumak için verilen anahtarlar tablosu ve engelleme darboğazı yoktur.

Bu, bize gerçekten benzersiz oldukları için tüm veritabanları boyunca, tüm kuruluşumuz genelinde benzersiz kimlikler verdi.

Verileri hız ve boyutun daha küçük Tamsayı anahtarları kullanarak belirtildiği bir Veri Ambarı / Küpüne getirmeye çalıştığınızda elbette fiyat alan ve sorunludur.

Ben onları kullanarak sonucu bizim app birçok hata kaçındı ikna oldum.


4

Tüm tablolarda tek bir sıralamanın ardındaki nedenin ne olabileceğini hayal bile edemiyorum. Tek yaptığı, yeni değerler üretirken bir darboğaz yaratmak.

Sıralı anahtar değerleri üretmenin yükü ne kadar küçük olursa olsun, jeneratör tek bir kaynaktır ve erişimi senkronize edilmelidir. Ne kadar çok istek alırsa, bazı isteklilerin muslukta dönüşlerini beklemek zorunda olma şansı o kadar yüksek olur. Tüm tablolar arasında paylaşılan tek sekans üretecine daha fazla istemci tarafından daha sık erişileceği ve böylece birden fazla üretecin herhangi birinden daha fazla çekişme üreteceği açıktır. İş kuralları, boşlukların veya katı siparişin olmaması veya oluşturulan bir veritabanı gibi oluşturulan değerlere kısıtlamalar getirdiği takdirde çekişme daha belirgin hale gelebilir.

En verimli dizi jeneratörü ile bile, dayanılmaz çekişmeye neden olan bir iş yükü olacaktır .


2
Darboğazın nasıl oluşturulduğu ve bunun neden kötü bir fikir olduğu hakkında ayrıntılar eklemek isteyebilirsiniz.
Max Vernon

2

Database tablolarındaki PrimaryKey'nin amacı öncelikle benzersiz olması gereken verilerin benzersizliğini zorunlu kılmaktır, çünkü tüm iş akışları kaplanamaz ve verilerin çoğaltılmasına neden olmayacağından emin olamaz. İkinci neden, çoğu zaman PK'nın aynı zamanda tablodaki kümelenmiş Dizin için birincil aday olması, bu nedenle bu sorgunun seçme sorgusunda uygun şekilde kullanıldığında / kullanıldığında verilerin alınmasını hızlandırmasıdır.

Birincil anahtar olarak bir sıra numarası kullanmak, her tablonun Kimlik sütununa sahip olmasıyla aynıdır ve PrimaryKey'de yalnızca bu sütun kullanılır. DB boyunca tek sıra numarasına sahip bazı özel kullanım olmalıdır ama PrimaryKey açısından neden anlamıyorum. örneğin üzerinde çalıştığım Datawarehouse projelerinden birinde LoadBatchID adlı bir Sütunumuz var ve ETL'den tüm tablonun% 50'sini bildirmeye kadar bu sütun var, ancak bazı yerlerde farklı bir anlamı var. çakışmaları bulamadığımızdan emin olmak için benzersiz proc'u sayı üreticisi olarak kullandık ve ayrıca verilerin geldiği yerden ve ETL'nin her farklı aşamasında neler olduğunu orijinal dosyaya kadar izlememize yardımcı olduk.


2

Sanırım bunu yapmak için bir neden, tüm varlıklar bir üst varlıktan miras alınırsa olurdu. Örneğin, herhangi bir varlık türüne yorum eklemek istediğinizi varsayalım:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Genellikle bu yapılmaz. .

Performans özelliklerini bilmiyorum.

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.