SQL - çoktan çoğa tablo birincil anahtarı


125

Bu soru, bu soruya bir yorum okuduktan sonra ortaya çıkıyor:

Veri tabanı tasarımı

Çoktan çoğa bir tablo oluşturduğunuzda, iki yabancı anahtar sütununda bileşik birincil anahtar mı yoksa otomatik artış yedek "Kimlik" birincil anahtarı mı oluşturmalı ve iki FK sütununuza (ve belki de benzersiz bir kısıt)? Her durumda yeni kayıt eklemenin / yeniden indekslemenin performans üzerindeki etkileri nelerdir?

Temel olarak, bu:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)

buna kıyasla:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)

Yorumcu şöyle diyor:

iki kimliği PK yapmak, tablonun diskte bu sırayla fiziksel olarak sıralandığı anlamına gelir. Dolayısıyla, (Part1 / Device1), (Part1 / Device2), (Part2 / Device3), ardından (Part 1 / Device3) eklersek, veritabanı tabloyu parçalara ayırmalı ve sonuncuyu 2 ile 3 arasındaki girişler arasına eklemelidir. birçok kayıt, her eklendiğinde yüzlerce, binlerce veya milyonlarca kaydı karıştırmayı içerdiğinden bu çok sorunlu hale gelir. Buna karşılık, otomatik artan PK, yeni kayıtların sonuna kadar takip edilmesine izin verir.

Sormamın nedeni, her zaman yedek otomatik artış sütunu olmadan bileşik birincil anahtarı yapmaya meyilli olmam, ancak vekil anahtarın aslında daha performanslı olup olmadığından emin değilim.


SO'da yayınlanan bir silimar sorusu: stackoverflow.com/questions/344068/…
Tony

(Bunu önceki yorumuma eklemeye çalıştım ama yapamıyorum) Eklemelerin sayısına bağlı olarak, sonuçları hızlı bir şekilde döndürmesini sağlamak için dizininizi periyodik olarak yeniden oluşturabilirsiniz. SQL Server'da, verileri hareket ettirmeden önce eklemeler için yeterli alan sağlamak üzere dizinin FILLFACTOR'ını da değiştirebilirsiniz.
Tony

1
Bunun cevabı hangi DBMS'nin kullanıldığına bağlı değil mi? MySQL'in bu durumda bir şekilde davranacağından şüpheleniyorum, SQL-Server biraz başka bir şekilde vs.
Radu Murzea

Uyarı: Belirli bir veritabanı etiketi olmadan, burada söylenenlerin çoğu şüphelidir. Farklı motorlar farklı çalışır!
Rick James

Yanıtlar:


85

Basit bir iki sütunlu çoktan çoğa eşlemeyle, bir vekil anahtara sahip olmanın gerçek bir avantajı görmüyorum. Bir birincil anahtara sahip (col1,col2)olmanın benzersiz olması garanti edilir ( başvurulan tablolardaki sizin col1ve col2değerlerin benzersiz olduğu varsayılarak ) ve ayrı bir dizin (col2,col1), ters sıranın daha hızlı yürütüleceği durumları yakalar. Vekil, bir yer israfıdır.

Tablo her zaman yalnızca başvurulan iki tabloyu birleştirmek için kullanılacağından, ayrı sütunlarda dizinlere ihtiyacınız olmayacaktır.

Soruda bahsettiğiniz yorum bence kullandığı elektronlara değmez. Yazar, tablonun son derece yüksek performanslı, dengeli, çok yönlü bir ağaç yapısı yerine bir dizide depolandığını düşünüyor gibi görünüyor.

Başlangıç ​​için, sıralanan tabloda saklamak veya almak hiçbir zaman gerekli değildir , sadece dizini. Ve endeks olmayacak saklanan hızla alınacak edebilmek için verimli bir şekilde saklanabilir edeceğiz sıralı.

Ayrıca, veritabanı tablolarının büyük çoğunluğu yazılandan çok daha sık okunur . Bu, seçilen tarafta yaptığınız her şeyi kesici taraftaki herhangi bir şeyden çok daha alakalı hale getirir.


Son nokta iyi bir genelleme değildir: "Veritabanı tablolarının büyük çoğunluğu, yazılandan çok daha sık okunur". Çok sık yazılması gereken birçok ilişkilendirilebilir tablo örneği buluyorum, örneğin müşteriyi siparişe bağlayan bir tablo.
kullanıcı

5
@buffer, bu yorumun yanında olacağım (teknik olarak, sadece "tüm tablolar" dersem, "büyük çoğunluk" deneyime dayalıdır). Örneğinizi de düşünelim, bir sipariş bir kez oluşturulur (ara sıra güncellenebilir, ancak bu, anahtar / dizin bilgilerini değiştirme olasılığı düşüktür, sipariş durumu gibi şeylere daha çok hitap eder. Ancak, bu güncellemeler ve yapmanız gereken seçimler faturaları yazdırmak veya yönetim raporları oluşturmak orijinal
eke göre

Amazon'u düşünün - Her saat binlerce sipariş oluşturulur.
kullanıcı

9
@buffer, evet, ancak yine, bu siparişlerin her biri neredeyse kesinlikle birçok kez sorgulanacak (örneğin) paketleme, faturalama, durum güncellemeleri, iş analitiği vb. Mutlak yaratma sayısı, yaratma ve okuma arasındaki orandan daha az önemlidir .
paxdiablo

1
Demek istediğim, insertsaatte binlerce kez yapılıp yapılmadığı önemli olacak. Sadece oranı sırf bunu göz ardı edemeyiz insertiçin selectbu durumda <ise 1., bu sipariş için gereken ne kadar zaman bir müşteri umurunda.
kullanıcı

19

Bağlantı tabloları için vekil anahtar gerekmez.

Tek ihtiyacınız olan bir PK (col1, col2) ve başka bir benzersiz dizin (col2, col1)

DB tasarımınızın üstesinden gelemeyen ve sizin için dikte eden bir ORM kullanmadığınız sürece ...

Düzenleme: Burada da aynı cevabı verdim: SQL: Many-Many tabloları için otomatik artan birincil anahtara ihtiyacınız var mı?


3
(Col2, col1) üzerinde benzersiz bir dizin yerine col2'de bir dups dizini ile sorun olmayabilirsiniz. İki sütunlu dizinin avantajı, yalnızca col2'de veya hem col1 hem de col2'de yalnızca dizin taramalarına izin vermesidir (ancak (col1, col2) üzerindeki diğer dizin de 'her ikisi' durumunu ele alır). Olumsuz tarafı, ekstra sütun için gereken ekstra depolama alanıdır. Bu genellikle önemli değildir, bu nedenle tavsiye kötü olmaktan uzaktır. Bununla birlikte, col1 ve col2 büyükse veya çok farklı boyutlardaysa, ikinci dizini yalnızca daha kısa sütunda almayı seçerek performansa zarar vermeden kendinize biraz alan kazandırabilirsiniz.
Jonathan Leffler

@gbn: (col2, col1) üzerindeki ikinci dizinin benzersiz olması gerekmez, değil mi?
kullanıcı

1
Zaten bir PK olduktan sonra (col1, col2) üzerine benzersiz bir dizin koymak tamamen gereksizdir
Don Cheadle

@mmcrae: Bunu nerede yapıyoruz?
gbn

2
@mmcrae: Yorumunuz "(col1, col2) .. üzerine benzersiz bir dizin koyma" şeklindedir. Bir dizindeki sütun sırası önemlidir. (col2, col1)değil (col1, col2). PK (col1, col2)tüm sorgular için uygun olmayabilir ve taramalar oluşturabilir, bu nedenle bunun tersine sahip olmak, col2'nin daha iyi olduğu yeri aramaya izin verdiği için performansı artırır. Örneğin, col2 içeren tabloda bir silme olduğunda FK doğrulaması. Çocuk masası kirleri kontrol edilecek
gbn

12

Tabloya başvurulursa artımlı bir birincil anahtar gerekli olabilir. Çoktan çoğa tabloda, artımlı birincil anahtar kullanılarak başka bir tablodan yukarı çekilmesi gereken ayrıntılar olabilir.

Örneğin

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details

FK olarak PartDevice.ID'yi kullanarak 'Diğer Ayrıntıları' almak kolaydır. Bu nedenle artımlı birincil anahtarın kullanılması gerekir.


1
Teşekkürler! Anlattığınız neredeyse aynı senaryoyu ararken cevaba geldim. Ancak "Diğer ayrıntılar" ekleyerek ilk cümlenizden uzaklaştınız. Ya başka bir tablodan başvurmam gereken çoktan çoğa eşleme tablosum olsaydı? Yani, çoktan çoğa eşleme tablosu başka herhangi bir bilgi depolamadı ... Ek Kimlik sütunu yine de mantıklı olur mu? Değilse, bunun yerine eşleme tablosunun bir kaydına nasıl başvurulur?
misanthrop

Burada iki seçenek vardır, referans tablonuzdan yabancı anahtar olarak bileşik anahtarı kullanabilirsiniz (bu, yeni tablonuza fazladan bir sütun ekler) veya eşleme tablosuna bir kimlik sütunu oluşturabilir ve orijinal bileşiğe benzersiz kısıtlama ayarlayabilirsiniz. Yeni id sütunu birincil anahtar olurken birincil anahtar.
Vočko

6

Sorunuza cevap verebilmemin en kısa ve en doğrudan yolu, bağladığınız iki tablonun sıralı birincil anahtarlara sahip olmaması durumunda bir performans etkisi olacağını söylemektir. Sizin de belirttiğiniz / aktardığınız gibi, bağlantı tablosunun dizini ya parçalanır ya da bağlantı tablosunun kendi sıralı birincil anahtarı yoksa DBMS kayıtları eklemek için daha çok çalışır. Çoğu kişinin bağlantı tablolarına sırayla artan bir birincil anahtar koymasının nedeni budur.


2

Öyleyse, YALNIZCA iş iki tabloyu bağlamaksa, en iyi PK, çift sütunlu PK olacaktır.

Ancak başka amaçlara hizmet ediyorsa, o zaman bir yabancı anahtar ve ikinci bir benzersiz dizine sahip bir PK olarak başka bir NDX ekleyin.

İndeks veya PK, kopya olmadığından emin olmanın en iyi yoludur. PK, Microsoft Management Studio gibi araçların sizin için bazı işleri yapmasına (görünümler oluşturmasına) izin verir

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.