Çoktan çoğa (birleşim) tabloda Benzersiz Kimlik sütunu gerekli midir?


22

EF ile birkaç projeye başladım, ancak katılım masaları ve anahtarlar vb. İle ilgili bazı sorularım oldu. Başvuruların birçok izni vardır ve her izin birçok uygulamaya (birçok kişiye) ait olabilir.

Şimdi, Başvuru ve İzin tabloları kolaydır:

Applications
--------------
PK  ApplicationID
    Name

Permissions
--------------
PK  PermissionID
    Name

Peki, katılım masasını yapmanın en iyi yolu nedir? Bu iki seçeneğim var:

ApplicationPermissions
-----------------------
PK  ApplicationPermissionID
CU  ApplicationID
CU  PermissionID

VEYA

ApplicationPermissions
-----------------------
CPK ApplicationID
CPK PermissionID

PK = Primary Key
CPK = Composite Primary Key
CU = Composite Unique Index

Hiç bir şekilde ötekine giderken yandın mı? kesinlikle tercih mi? “Farklılıkların” çoğunun depo şablonumla soyutlanacağı aklıma geldi (örneğin, neredeyse hiç bir zaman izin nesnesi oluşturmaz ve bir uygulamaya eklemezdim, ancak kimliği veya benzersiz bir ad veya bir şey), ama sanırım bir ya da başka bir korku hikayesi arıyorum.

Yanıtlar:


20

Sanırım "birleşme" tablosu, "birleştirme" tablosu değil.

Bir kavşak tablosunun kendi ID alanına sahip olması gerekmez. Böyle bir kimliğe asla katılmanıza veya filtrelemenize gerek kalmaz. Eşlediğiniz tabloların kimliklerini yalnızca katılabilirsiniz veya filtreleyebilirsiniz. Bağlantı tablosundaki bir kimlik, disk alanı israfıdır.

Yani "en iyi" seçenek kimliği önlemek için. Tipik olarak bir birleşme tablosu 2 kaplama indeksine sahip olacaktır. Eşlenen kimlik numaralarından birini birincil sıralama alanı olarak kullanan her bir kaplama dizini.

Ancak "en iyi" uzun bir atış tarafından değil. Yedekli bir kimlik alanına sahip olmak çok küçük bir konudur. Az miktarda boşa harcanan disk üzerinde hiçbir korku hikayesine sahip olmayacaksınız. Kimlik, kümelenmiş dizini "çalmayacak" çünkü eşlenmiş combo üzerinde kümelenmek istemiyorsunuz.

Çerçeveniz tüm tabloların bir kimliğine sahip olmasını istiyorsa, bunun için gidin. Ekibinizin veritabanı standartları, tüm tabloların bir kimliğine sahip olması gerektiğini belirtirse, bunun için gidin. Eğer değilse, o zaman kaçının.


2
Eh, zaten bir kimlik eklemenin küçük bir imtiyaz olduğunu, potansiyel faydalarla kolayca üstesinden geldiğini söylemiştin, bu yüzden bana öyle geliyor ki (her tabloda benzersiz bir kimlik belgesi olması çoğu DBMS ve ORM’de az çok en iyi uygulama olduğu için) Bir kimliğe sahip olmamak yerine "en iyi" ya da "varsayılan" seçenek olarak bir kimliğe sahip olmayı savunuyorsunuz .
Robert Harvey

4
“Hiçbir zaman böyle bir kimliğe katılmaya veya sorgulamaya gerek kalmaz” - bir teknoloji durumunda “asla” derken o şeyi yapmaya davet ediyoruz. Söyleyerek, orada olan katıldı kişiler aslında a'da çünkü dördüncü tabloya henüz tabloyu katılmak Katılacağınız kez (evet, ben bir daha bir "kavşak" tablosunun daha tabloyu "katılmak" olarak anılacaktır duydum) kendi iş nesnesi.
Jesse C. Dilimleyici

4
@RobertHarvey. Kimlik, kurumlar için iyi bir uygulamadır. Ancak bir kavşak, pek çok ilişki için kendi başına bir varlık değil, bir uygulama detayıdır. Ancak Jesse C. sürgüsünün işaret ettiği gibi, bir kavşağın bir işletme varlığı olarak düşünülebileceği durumlar vardı.
mike30

1
"disk alanı israfı." - Sanırım bazı motorlar (InnoDB?) Kendi kendinize bir tane yapmazsanız (dahili) bir birincil anahtar yaratır - bu yüzden aslında sahip olmadığınız bir disk alanı kazanamayabilirsiniz.
Alex

@Alex. Eşlenen kimlikleri üzerine bileşik bir PK koyun.
mike30,

11

Yıllar geçtikçe, her bir tabloyu "TabloAdı" na otomatik olarak oluşturulan bir birincil anahtar "TabloAdı Kimliği", alışılmadık bir tablo olmadan bile, alışkanlık haline getirdim. Asla pişman olmadığımı söyleyebilirim, çünkü "tüm tablolar" veya "bazı tablolar" veya "birkaç farklı tablodaki birçok satır" için bir şeyler yapan genel kod oluştururken bir çok şeyi kolaylaştırır.

Örneğin, bir kişi sizden farklı tabloların (veya bunlara referansların) bazı satırlarını bir dosyada veya bellekte saklamanızı isterse, örneğin, günlük tutma amacıyla, önceden tam olarak bir tane kaydetmeniz gerektiğini bilmeniz çok yararlıdır. tablo adı ve tam olarak bir tam sayı kimliği ve herhangi bir "özel durum" ile uğraşmanıza gerek yok.

Başka bir şey, birleşik PK'larla başladığınızda, muhtemelen birkaç kez sonra birleşik yabancı anahtarlara ihtiyaç duyacaksınız (çünkü ApplicationPermissionstablonuza FK ref eklemek istediğiniz bir noktaya gelebilirsiniz ). Öyleyse, bir sonraki gereklilik, bu FK'nin, diğer özelliklerle veya yabancı anahtarlarla birlikte benzersiz olması ve bunun da karmaşıklığın artmasıyla sonuçlanması olabilir. Elbette çoğu modern DB sistemiyle başa çıkmak mümkün olmayan hiçbir şey, elbette, ancak tek tip bir çözüm programcılar için hayatı çok daha kolay hale getiriyor.

Ve son olarak, böyle bir ifade SELECT ... FROM TABLE WHERE TableNameID IN (id1,id2,...)birincil anahtar olarak tek bir sütunla iyi çalışır, ancak bunu birleştirilmiş bir tuşla yapmanıza izin veren bir SQL lehçesi görmedim. Önceden böyle bir sorguya ihtiyacınız olmayacağını önceden biliyorsanız, sorun değil, ancak yarın bu tür bir SQL ile en kolay şekilde çözülecek bir gereksinim alırsanız şaşırmayın.

Elbette, ApplicationPermissionsmasanızın birkaç yüz milyon satır beklemesini beklediğinizde, a gibi bir şeyden kaçınmalısınız ApplicationPermissionsID.


Yine de cevabını seçmedim. Ben onun yönlerini severim. Düşünceleriniz için teşekkürler (oy verin).
solidau

6

Mike'ın cevabı iyi olsa da, ayrı bir kimlik alanı ekleyip eklemememin nedenleri.

  1. ID'den başka alanlar içeriyorsa , birleşme / birleştirme tablosu için ayrı bir ID alanı kullanmayı düşünün . Bu, birinci sınıf bir varlık olduğunu not etmek eğilimindedir.

  2. API'ler veya var olan herhangi bir mantık, varlıkları almak / düzenlemek için tek alanlar kullanmaya eğilimliyse, ayrı bir ID alanı kullanmayı düşünün. Bu, başkalarının daha büyük bir proje bağlamında kodunuzu takip etmesine yardımcı olabilir.

  3. Belirli bir yararı yoksa (KISS) kullanmayın. EF, bu tür bir masanın nasıl kullanılacağını bilir ve kompozit benzersiz bir kısıtlama, başkaları bu tip bir ilişkiyi anlamaya çalışırken bazen kaçırılabilir. Ayrıca, normalleştirirken , eşitliği benzersiz şekilde tanımlayan en küçük anahtarı kullanmaya çalışıyorum . İkinci örnekte, 2 ayrı aday birincil anahtarınız var.


-5
table Person
   Id int identity(1,1) not null primary key
   ...other fields go here...
table Address
   Id int identity(1,1) not null primary key
   ...other fields go here...
table PersonAddress
   Id int identity(1,1) not null primary key
   PersonId int not null
   AddressId int not null

Hem bir dizin ve yabancı anahtar oluşturmayı unutmayın PersonIdve AddressId.

Başkalarının ne düşündüğünün önemi yok "daha iyi" ya da "yapmalı", bu veritabanının düzgün çalışabilmesi için en basit ve en kolay yoldur.


1
Bence bu yaklaşımla ilgili bir sorun şema PersonAddressaynı PersonIdve AddressIddeğerlere sahip iki satıra izin veriyor .
Sam,
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.