Yabancı anahtarların nesi var?


259

Ben işitme hatırlıyorum Joel Spolsky içinde söz podcast 014 (eğer doğru hatırlıyorsam) o zorlukla hiç bir yabancı anahtar kullanmış edeceğini. Ancak, bana veritabanı boyunca yineleme ve sonraki veri bütünlüğü sorunları önlemek için oldukça hayati görünüyor.

İnsanların neden olarak bazı sağlam nedenleri var mı (Yığın Taşması ilkeleri doğrultusunda tartışma yapılmasını önlemek için)?

Düzenleme: "Henüz bir yabancı anahtar oluşturmak için bir nedenim var, bu yüzden bu aslında bir tane kurmak için ilk nedenim olabilir."


9
Joel'in FKs kullanmadığını sanmıyorum, sadece veritabanını onları zorlamıyor. Mantıken, hala FK'ler!
Daren Thomas

6
Yabancı anahtar kullanmadığını söylüyor ama Daren'e katıldığım şeyin yabancı anahtar KISITLAMALAR kullanmaması olduğunu kabul ediyorum. Bir tabloda, başka bir tablonun birincil / benzersiz anahtarından alınması gereken bir sütun, kısıtlama ekleseniz de eklemeseniz de yabancı anahtarlardır.
Tony Andrews

22
... Genellikle kısıtlama eklememek aptalca: uygulama kodunda bir hata olsa bile veya bir veri "düzeltme" yaparken sahne arkasında çalışıyorsanız bile, her zaman bütünlüğü sağlar.
Tony Andrews

2
+1 Tony'nin yorumu için. Bu özellik ile oradaki yabancı anahtarların mantıksal konsepti arasında çok fazla kafa karışıklığı var.
JohnFx

4
@DanMan, izlenimi nereden aldığını bilmiyorum bence. Aslında yukarıda diyorum ki "Genellikle kısıtlama eklememek aptalca: her zaman bütünlük sağlar"
Tony Andrews

Yanıtlar:


352

Yabancı Anahtarları kullanma nedenleri:

  • Artık Satırlar almayacaksınız
  • tabloları otomatik olarak temizleyerek güzel "basamaklı silme" davranışı alabilirsiniz
  • veritabanındaki tablolar arasındaki ilişkileri bilmek, birleştirme kardinalitesi hakkında daha iyi tahminler alabildiğinden, Optimize Edici'nin sorgularınızı en verimli yürütme için planlamasına yardımcı olur.
  • FK'ler, hangi istatistiklerin veritabanında toplanmasının en önemli olduğuna dair oldukça büyük bir ipucu verir ve bu da daha iyi performans sağlar
  • otomatik olarak oluşturulan her türlü desteği sağlarlar - ORM'ler kendilerini üretebilir, görselleştirme araçları sizin için güzel şema düzenleri oluşturabilir.
  • projede yeni olan biri daha hızlı bir şekilde iş akışına girecektir, aksi takdirde örtük ilişkiler açıkça belgelenmiştir

Yabancı Anahtarları Kullanmamanın Nedenleri:

  • FK tutarlılığını kontrol etmesi gerektiğinden DB'yi her CRUD işleminde fazladan yapıyorsunuz . Çok fazla yayık varsa bu büyük bir maliyet olabilir
  • ilişkileri uygulayarak, FK'ler bir şeyler eklemeniz / silmeniz gereken bir sıra belirler, bu da DB tarafından istediğinizi yapmayı reddetmeye neden olabilir. (Bu gibi durumlarda, yapmaya çalıştığınız şey Artık bir Satır oluşturmaktır ve bu genellikle iyi bir şey değildir). Bu, özellikle büyük toplu güncellemeler yaparken ve bir tabloyu diğerinden önce yüklediğinizde, ikinci tablo tutarlı bir durum oluşturduğunuzda (ancak ikinci yükün başarısız olması ve veritabanı artık tutarsız mı?).
  • bazen önceden verilerinizin kirli olacağını bilirsiniz, bunu kabul edersiniz ve DB'nin bunu kabul etmesini istersiniz
  • sen sadece tembelsin :-)

Bence (emin değilim!) En yerleşik veritabanları zorlanmış bir yabancı anahtar belirtmek için bir yol sağlar ve sadece biraz meta veri olduğunu düşünüyorum. Yaptırmama FK'leri kullanmamak için her nedenini sildiğinden, ikinci bölümdeki nedenlerden herhangi biri geçerliyse muhtemelen bu rotaya gitmelisiniz.


12
İyi liste! DBM'ler CRUD "R" parçası için tutarlılık kontrol olmaz, bu yüzden o kısmı çıkar. Ayrıca, muhtemelen bir yıkama çünkü uygulamanızda DBMS'nin yaptığı aynı şeyi yaparsınız: Ana kimliğin CRD'den önce geçerli olduğundan ve aslında DBM'lerin yapmasından daha yavaş olduğundan emin olacaksınız!
Matt Rogish

6
Çocuk eklerken birisi ebeveyni silerse ne olur? Şu anda "yorum ekle" yi gönderdiğimde - yanıtınızı daha önce sildiyseniz, bu yorum artık bir yetimdir. FK'ler bunu önlerdi. Ayrıca, parentID değerini istediğim herhangi bir şey olarak değiştirebilirim. Birisinin kontrol etmesi gerekiyor. :)
Matt Rogish

7
Tam olarak - DB'nin işi olmalı, çünkü birden fazla eşzamanlı müşteri karşısında işlemciliği garanti edebilen tek iş budur.
SquareCog

3
+1 Mükemmel cevap - FK kısıtlamalarını kullanmamanın ikinci nedeni, aslında iyi bir şey gibi görünen "tutarlılığı kırmayı zorlaştırır" olarak düşünülebilir !
Bill Karwin

9
Yabancı anahtarlar kullanmanın faydaları FAR, bence bunları kullanmamanın avantajlarından daha ağır basmaktadır.
Nick Bedford

80

Bu bir yetiştirme meselesidir. Eğitim veya profesyonel kariyerinizde bir yerde veritabanlarını beslemek ve bakım yapmak için zaman harcadınız (veya yetenekli kişilerle yakın çalıştınız), o zaman varlıkların ve ilişkilerin temel ilkeleri düşünce sürecinizde köklüdür. Bu ilkeler arasında veritabanınızdaki anahtarların nasıl / ne zaman / neden belirtileceği (birincil, yabancı ve belki de alternatif). İkinci doğa.

Bununla birlikte, RDBMS ile ilgili girişimlerde geçmişinizde bu kadar kapsamlı veya olumlu bir deneyiminiz yoksa, muhtemelen bu tür bilgilere maruz kalmamışsınızdır. Belki de geçmişiniz, veri tabanı anti-veritabanı gibi bir ortama daldırma içerir (örn., "Bu DBA'lar aptallardır - biz azız, birkaç java / c # kod saptırıcısı günü kurtaracaktır"), bu durumda şiddetle karşı çıkabilirsiniz bazı dweeb'lerin gizli bebeklerine, FK'ların (ve ima edebilecekleri kısıtlamaların) gerçekten dinlerseniz gerçekten önemli olduğunu söyler.

Çoğu çocuk dişlerini fırçalamanın önemli olduğu çocukken öğretildi. Onsuz geçebilir misin? Tabii, ama çizginin bir yerinde her yemekten sonra fırçalamış olsaydınız, sahip olabileceğinizden daha az dişiniz olacak. Anneler ve babalar, ağız hijyeninin yanı sıra veritabanı tasarımını da kapsayacak kadar sorumlu olsaydı, bu konuşmayı yapamazdık. :-)


61
Damıtılmış "yabancı anahtarları dişlerini fırçalamak gibi kullanacağım: devam et, onsuz yap, ama gülümsediğinde dikkatli ol"
Mark Sowul

5
Şahsen RDBMS 'ilkelerinin ağız hijyeni kurallarından çok daha basit ve çok daha iyi tanımlandığını
görüyorum

Gelecekte 10 yıl, eminim bu veritabanı tasarımı oğlum / kızım ile konuşmak olacak, bu yüzden o dağınık ve bir veritabanı sorunu nedeniyle bir sonraki wall street çökmesine neden olur.
VarunAgw

52

Eminim bundan kurtulabileceğiniz birçok uygulama vardır, ancak bu en iyi fikir değildir. Veritabanınızı düzgün bir şekilde yönetmek için her zaman uygulamanıza güvenemezsiniz ve açık bir şekilde veritabanını yönetmek uygulamanız için çok fazla endişe duymamalıdır.

İlişkisel bir veritabanı kullanıyorsanız, o zaman bazı ilişkilerin tanımlanmış olması gerekir. Ne yazık ki bu tutum (yabancı anahtarlara ihtiyacınız yok), veri bütünlüğü gibi aptalca şeylerle uğraşmak istemeyen birçok uygulama geliştiricisi tarafından kucaklanıyor gibi görünüyor (ancak şirketlerinin özel veritabanı geliştiricileri olmadığı için buna ihtiyaç var). Genellikle bu türler tarafından bir araya getirilen veritabanlarında sadece birincil anahtarlara sahip olduğunuz için şanslısınız;)


26
Veri tabanlarında FK olmayan insanları gerçekten alamıyorum. En son sahip olmadığım biriyle çalıştığımda, "hayır, bunu uygulamada uygularız" dedi. Tüm müşteri veritabanları hakkında bir anket yaptım ve çoğunun yetim olduğunu
gördüm

1
Genellikle durum böyle görünüyor. SADECE veritabanında zorlama ile kurtulmak düşünüyorum (kullanıcılarınız çalışma zamanı istisnalar sakıncası yoksa) ama her ikisi de gerçekten gitmek için tek yoldur.
AlexCuse

Bunların hepsi transkriptler / Atwood'un cevabı "Atwood: ... dizinlerde ayarladığınız yabancı anahtarlara dayanarak, anlıyorlar ... Spolsky: [gülüyor] Bunu yaptığınızı varsayarsak. veritabanınızı doğru ayarladınız ... "
MemeDeveloper

4
Veritabanı denilen değildir ilişkisel nedeniyle ilişkiler tablolar arasında (veritabanı HER tür varlıklar arasındaki ilişkilerin bir çeşit var!), Ancak tablolar çünkü kendileri ilişkiler matematik açısından,. Wikipedia'ya bakın .
Massimiliano Kraus

41

Yabancı anahtarlar herhangi bir ilişkisel veritabanı modeli için gereklidir .


54
Model, evet. Uygulama zorunlu değil, muhtemelen yararlıdır.
dkretz

4
Üzgünüz, ancak uygulama geliştiricilerinin nesne veritabanı yönetim sistemlerini (diğer adıyla NoSQL veritabanları!) Kullanmamalarının ana nedeni RDBMS'lere yapılan yatırımdır. Çoğu zaman veritabanı (veritabanı yönetim sistemi değil), genellikle dağıtılmış önbellekleri içeren orta seviye bir nesne modelidir. Burada, silme basamaklaması, sahiplik ve değişikliklerin senkronizasyonu yine de gerçekleşmelidir. RDBMS öncelikle bu nesne modelinin kalıcılığı için ve genellikle özenli ve pratik olarak değersiz bir ORM egzersizinden sonra kullanılır. İlişki modelleri çoğu zaman gerekli değildir!
Sentinel

2
hayır, yabancı anahtarlar "ilişkisel" belirtmek için zorunlu değildir
Silver Moon

Bu pek bir şey anlatmıyor.
Nae

29

Onları her zaman kullanıyorum, ama sonra finansal sistemler için veritabanları yapıyorum. Veritabanı uygulamanın kritik kısmıdır. Bir finansal veritabanındaki veriler tamamen doğru değilse, kod / ön uç tasarımınıza ne kadar çaba harcadığınız önemli değildir. Sadece zamanını boşa harcıyorsun.

Ayrıca, birden çok sistemin genellikle doğrudan veritabanıyla arayüz oluşturması gerektiği gerçeği de vardır - sadece veri okuyan diğer sistemlerden (Crystal Reports) veri ekleyen sistemlere (tasarladığım bir API kullanmadan ille de olabilir; VBScript'i yeni keşfetmiş ve SQL kutusu için SA parolasına sahip donuk zekâlı yönetici). Eğer veritabanı olabildiğince aptal geçirmez değilse, hoşçakalın veritabanı.

Verileriniz önemliyse, evet, yabancı anahtarlar kullanın, verilerle etkileşim kurmak için bir dizi saklı yordam oluşturun ve yapabileceğiniz en zorlu DB'yi yapın. Verileriniz önemli değilse, neden başlamak için bir veritabanı hazırlıyorsunuz?


2
İyi fikir. Verilerin aslında kullanılan her uygulama için bu kadar önemli olduğunu iddia ediyorum. Farklı olan tek şey bozuk verilerin sonuçlarıdır. Senin tür uygulama için yüksek ...
Jay Godse

20

Güncelleme : Şimdi her zaman yabancı anahtar kullanıyorum. "Onlar karmaşık test" itirazına cevabım "hiç bir veritabanına ihtiyaç yok böylece birim testleri yazmaktır. Veritabanını kullanan herhangi bir test düzgün kullanmalı ve yabancı anahtarlar içerir. Kurulum acı veriyorsa, kurulumu yapmanın daha az acı verici bir yolunu bul. "


Yabancı anahtarlar otomatik testi zorlaştırır

Yabancı anahtarlar kullandığınızı varsayalım. "Bir finansal hesabı güncellediğimde, işlemin bir kaydını kaydetmelidir" yazan otomatik bir test yazıyorsunuz. Bu testte yalnızca iki tablo ile ilgileniyorsunuz: accountsve transactions.

Ancak, accountsyabancı bir anahtar vardır contractsve contractsbir fk sahiptir clientsve clientsbir fk sahiptir citiesve citiesbir fk sahiptir states.

Artık veritabanı, testinizle ilgili olmayan dört tabloda veri ayarlamadan testinizi çalıştırmanıza izin vermeyecektir .

Bununla ilgili en az iki olası bakış açısı vardır:

  • "Bu iyi bir şey: testiniz gerçekçi olmalı ve bu veri kısıtlamaları üretimde mevcut olacak."
  • "Bu kötü bir şey: Sistemin test parçalarını başka parçalar dahil etmeden birleştirebilmelisiniz. Sistem için bir bütün olarak entegrasyon testleri ekleyebilirsiniz."

Testler yapılırken yabancı anahtar kontrollerini geçici olarak kapatmak da mümkün olabilir. MySQL en azından bunu destekliyor .


Kendimi burada genellikle orta yolu seçiyorum: FK'ler kullanıyorum, sonra DB'yi çeşitli test senaryolarını destekleyecek şekilde ayarlayan birim testi yardımcı yöntemleri yazıyorum, örneğin herhangi bir test için "şehirleri" ve "durumları" doldurmak için bir yardımcı yöntem bu tabloları doldurmak gerekir.
joelpt

İlişkili olmayan varlıklar arasında bağlantı tabloları kullanmış olmalısınız. Veya daha ileri git - ayrı DBS: her bir öğenin (istemciler, hesaplar, işlemler) farklı DB'lere sahip farklı sistemler olduğu Hizmet Odaklı Mimari veya Mikro Hizmet'teki durumu göz önünde bulundurun. Aralarında hiçbir FK yok. Bu durumda, FK'ler her veri türü için alt tablolardaki artık verileri engellemek için kullanılmalıdır.
JeeBee

3
Ertelenen kısıtlamalara izin veren DBMS de vardır, böylece yalnızca tüm işlemi gerçekleştirdiğinizde kontrol edilirler, bu nedenle ekleme, güncelleme, silme sırası önemli değildir
a_horse_with_no_name 23:14

2
Bir iş katmanından bir güncellemeyi test ediyorsanız, geliştirme ortamınızda FK mevcut olmalıdır. Kaydınızı güncellediğinizde, güncellemenin başarılı olması için gereken sütun değerlerine sahip olmanız gerekir. Aksi takdirde, IMHO testiniz geçerli değil.
KeyOfJ

3
Veritabanınız birim testlerinize dahil edilmemeli, onları alay etmelisiniz. Entegrasyon testinde yer alacaklardı, ancak yabancı anahtarlardan kaynaklanan herhangi bir sorun, düzeltmediğiniz sürece kullanıcılarınızın da karşılaşacağı bir şey.
Andreas Bergström

16

"Kayıtları silmeyi daha zor hale getirebilir - yabancı anahtarların bu kısıtlamayı ihlal edeceği diğer tablolarda kayıtların olduğu" ana "kaydı silemezsiniz."

SQL standardının, yabancı bir anahtar silindiğinde veya güncellendiğinde gerçekleştirilen işlemleri tanımladığını hatırlamak önemlidir. Bildiklerim:

  • ON DELETE RESTRICT- Diğer sütundaki bu sütunda anahtarları olan satırların silinmesini önler. Ken Ray yukarıda anlatılan buydu.
  • ON DELETE CASCADE - Diğer tablodaki bir satır silinirse, bu tablodaki ona başvuran satırları silin.
  • ON DELETE SET DEFAULT - Diğer tablodaki bir satır silinirse, sütunun varsayılan ayarına başvuran yabancı anahtarları ayarlayın.
  • ON DELETE SET NULL - Diğer tablodaki bir satır silinirse, bu tabloda başvuran yabancı anahtarları null değerine ayarlayın.
  • ON DELETE NO ACTION- Bu yabancı anahtar yalnızca yabancı anahtar olduğunu belirtir; yani VEYA haritacılarda kullanım içindir.

Aynı eylemler için de geçerlidir ON UPDATE.

Varsayılan, hangisine bağlı gibi görünüyor kullandığınız sunucu.


14

@imphasing - bu tam olarak bakım kabuslarına neden olan bir zihniyet.

Neden verinin, en azından zayıf bir önleyici tedbir olan "yazılım uygulaması" lehine , verilerin en azından tutarlı olacağı garanti edilebilecek beyan edici bütünlüğü göz ardı edersiniz .


Çünkü ilgili geliştiriciler hiçbir zaman önemsiz olmayan, normalleştirilmiş, ilişkisel bir model gerektiren bir sorunla mücadele etmediler. Pek çok sorun, özellikle web / "sosyal medya" türü programlamada bol miktarda bulunmayan, bugün çılgınca olan bir şey değil. Bir ORM çerçevesinin arka ucunu toplayan ne olursa olsun, alfadaki sorunu karşılıyorsa, veri modelleme hakkında daha fazla düşünmek mümkün değildir. Bu tür sorunların çoğu, K / V depoları, belge veritabanları veya düz nesne serileştirmeleri tarafından kolayca halledilir.
zxq9

12

Bunları kullanmamak için iyi bir neden var: Rollerini veya nasıl kullanılacağını anlamıyorsanız.

Yanlış durumlarda, yabancı anahtar kısıtlamaları kazaların şelale çoğalmasına neden olabilir. Birisi yanlış kaydı kaldırırsa geri almak mamut bir görev olabilir.

Ayrıca, tersine, bir şeyi kaldırmanız gerektiğinde, kötü tasarlanmışsa, kısıtlamalar sizi engelleyen her türlü kilitlere neden olabilir.


8
Üretimdeki bir satırı yedeklemeden silmek geçerli bir argüman değildir. Onları anlamıyorsanız, atlamak yerine öğrenmeyi düşünmelisiniz.
Guillaume

2
@Guillaume Bence cevabı biraz alaycıydı, kelimenin tam anlamıyla alınmamalı: eğer onları anlamıyorsanız, onları kullanmayın. Ama tabii gerektiğini hem anlamak ve bunları kullanın.
Benjamin

^ Bu. Bunlar yararlı araçlardır, ancak aceminin elinde tehlikeli araçlardır.
Kent Fredric

11

Hiçbir vardır iyi nedenler değil bunları kullanmak için ... yetim satırlar sanırım size büyük bir anlaşma değil sürece.


11
Öksüz satırlar neden önemli?
Seun Osewa

2
Çoklu okumaya ne dersiniz? Bazı durumlarda çok iş parçacıklı bir kabusa neden olabilirler. Birbirine başvurması gereken nesnelerle karşılaşabilecek veritabanını yazan birden çok iş parçacığı içeren karmaşık bir uygulamada, iş mantığındaki referans bütünlüğünü kontrol etmek daha iyidir - özellikle tablolar daha sonra statik olacaksa.
Keith Pinson

Katılıyorum. Ayrıca, daha sonra zamanında kurtarabileceğim ophan satırlarına sahip olmayı, onları acımasızca atmaktan daha çok tercih ederim.
PedroD

4

Daha büyük soru şudur: Göz bağı takılıyken araba sürer misiniz? Referans kısıtlamaları olmayan bir sistem geliştirirseniz böyle olur. İş gereksinimlerinin değiştiğini, uygulama tasarımı değişikliklerinin, kod değişikliklerindeki ilgili mantıksal varsayımların, mantığın kendisinin yeniden düzenlenebileceğini ve benzeri şeyleri unutmayın. Genel olarak, veritabanlarındaki kısıtlamalar, belirli mantıksal iddialar ve varsayımlar kümesi için doğru gibi görünen çağdaş mantıksal varsayımlar altında uygulanmaktadır.

Bir uygulamanın yaşam döngüsü boyunca, referans ve veri kontrolleri, özellikle yeni gereksinimler mantıksal uygulamayı değiştirdiğinde, uygulama yoluyla polis veri toplamayı kısıtlar.

Bu listenin konusuna - yabancı bir anahtar tek başına "performansı iyileştirmez" veya gerçek zamanlı işlem işleme sistemi açısından performansı "önemli ölçüde düşürmez". Ancak, YÜKSEK hacimli "parti" sisteminde kısıtlama kontrolü için toplu bir maliyet vardır. Yani, fark, gerçek zamanlı ve toplu işlem süreci; toplu işleme - ardışık olarak işlenmiş bir toplu işin kısıtlama denetimleriyle oluşan toplam maliyet bir performans isabeti oluşturur.

İyi tasarlanmış bir sistemde, bir seri işlenmeden "önce" veri tutarlılığı kontrolleri yapılacaktır (yine de burada da bir maliyet söz konusudur); bu nedenle, yükleme sırasında yabancı anahtar kısıtlama denetimlerine gerek yoktur. Aslında, yabancı anahtar dahil tüm kısıtlamalar, toplu iş işlenene kadar geçici olarak devre dışı bırakılmalıdır.

SORGULAMA PERFORMANSI - tablolar yabancı anahtarlarda birleştirilirse, yabancı anahtar sütunlarının İNDEKSLENMEDİĞİNİN farkında olun (ilgili birincil anahtarın tanımıyla dizine eklenmiş olmasına rağmen). Yabancı bir anahtarın endekslenmesi, herhangi bir anahtarın endekslenmesi ve endekslenmiş tabloların birleştirilmesi, endekslenmemiş anahtarın üzerinde yabancı anahtar kısıtlaması ile birleştirilmesiyle değil, daha iyi performans elde edilmesine yardımcı olur.

Nesneleri değiştirmek , eğer bir veritabanı sadece web sitesi görüntüleme / içerik oluşturma / vb. Bunu düşün. Çoğu web sitesi bunun için bir veritabanı bile kullanmaz. Verilerin sadece kaydedildiği ve her biri için referans verilmediği benzer gereksinimler için, kısıtlamaları olmayan bir bellek içi veritabanı kullanın. Bu, hiçbir veri modeli, evet mantıksal model olmadığı, ancak fiziksel veri modeli olmadığı anlamına gelmez.


Boşlukların yerine 3 adet çift yeni satır eklemenin ve iki kelimeyi '% 67 Jonathan Leffler' olarak değiştirmenin nedenini bilmiyorum, ama bunun üzerinde böyle bir şey yaptığımı sanmıyorum. Ana metne @jay (kullanıcı 183837) katkıda bulundu.
Jonathan Leffler

Ben sadece paragrahps diğer birçok sitede olduğu gibi burada işe yaramaz varsaydı. Böylece, akış değişikliği için kalınları kullanarak hepsini birer tane koydum.
yasbir L

3

Yabancı Anahtarları Kullanmanın Ek Nedeni: - Veritabanının daha fazla yeniden kullanılmasına izin verir

Yabancı Anahtarları KULLANMAMAK için Ek Neden: - Yeniden kullanımı azaltarak bir müşteriyi aracınıza kilitlemeye çalışıyorsunuz.


3

Deneyimlerime göre, Veritabanı Kritik Uygulamalarında FK kullanmaktan kaçınmak her zaman daha iyidir. Ben burada FKs iyi bir uygulama ama veritabanı büyük ve CRUD işlemleri / sn büyük olduğu pratik değil diyen çocuklar ile katılmıyorum. Adsız paylaşabiliyorum ... en büyük yatırım bankasından birinin veritabanlarında tek bir FK'si yok. Bu kısıtlamalar DB içeren uygulamalar oluşturulurken programcılar tarafından ele alınır. Temel nedeni, yeni bir CRUD yapıldığında, birden fazla tabloyu etkilemesi ve her bir ekleme / güncelleme için doğrulaması gerekir, ancak bu, tek satırları etkileyen sorgular için büyük bir sorun olmayacaktır, ancak bununla uğraşırken büyük bir gecikme oluşturur herhangi bir büyük bankanın günlük görevler olarak yapması gereken toplu işlem.

FK'lerden kaçınmak daha iyidir, ancak risk programcılar tarafından ele alınmalıdır.


8
Büyük bankalardaki kalkınma uygulamalarının altın standardı oluşturduğunu sanmıyorum.
Adriaan Koster

3

"Kayıt eklemeden önce, başka bir tabloda karşılık gelen bir kaydın var olup olmadığını kontrol edin" iş mantığıdır.

Veritabanında bunu istememenizin bazı nedenleri şunlardır:

  1. İş kuralları değişirse, veritabanını değiştirmeniz gerekir. Veritabanı birçok durumda dizini yeniden oluşturmanız gerekir ve bu büyük tablolarda yavaştır. (Değişiklik kuralları şunları içerir: yorum göndermesine rağmen davetlilerin mesaj göndermesine veya kullanıcıların hesaplarını silmesine izin verme vb.).

  2. Veritabanını değiştirmek, değişiklikleri üretim havuzuna göndererek bir yazılım düzeltmesi uygulamak kadar kolay değildir. Veritabanı yapısını mümkün olduğunca değiştirmekten kaçınmak istiyoruz. Veritabanında ne kadar çok iş mantığı varsa, veri baralarını değiştirme (ve yeniden endekslemeyi tetikleme) şansını o kadar artar.

  3. TDD. Birim testlerinde veritabanını alay yerine koyabilir ve işlevselliğini test edebilirsiniz. Veritabanınızda herhangi bir iş mantığınız varsa, tam testler yapmıyorsunuz ve ya veritabanı ile test etmeniz ya da iş mantığını test amacıyla kod olarak çoğaltmanız, mantığı çoğaltmanız ve mantığın aynı şekilde.

  4. Mantıklarınızı farklı veri kaynaklarıyla yeniden kullanma. Veritabanında mantık yoksa, uygulamam veritabanındaki kayıtlardan nesne oluşturabilir, bunları bir web hizmetinden, bir json dosyasından veya başka bir kaynaktan oluşturabilir. Sadece veri eşleyici uygulamasını değiştirmem gerekiyor ve tüm iş mantığımı herhangi bir kaynakla kullanabiliyorum. Veritabanında mantık varsa, bu mümkün değildir ve mantığı veri eşleyici katmanında veya iş mantığında uygulamanız gerekir. Her iki durumda da, kodunuzda bu denetimlere ihtiyacınız vardır. Veritabanında bir mantık yoksa, uygulamayı farklı veri tabanları veya düz dosya uygulamaları kullanarak farklı konumlara dağıtabilirim.


2

Önceki cevaplara veri tutarlılığını korumak için faydalı oldukları konusunda katılıyorum. Ancak, Jeff Atwood'un birkaç hafta önce normalleştirilmiş ve tutarlı verilerin artılarını ve eksilerini tartışan ilginç bir yazı vardı .

Birkaç kelimeyle, büyük miktarda veri işlenirken denormalize edilmiş bir veritabanı daha hızlı olabilir; ve uygulamaya bağlı olarak kesin tutarlılığı önemsemeyebilirsiniz, ancak veri tabanı ile uğraşırken, DB olmayacağı için sizi çok daha dikkatli olmaya zorlar.


Jeff iyi puanlar verir. Ancak, "Enterprise Rails" içindeki Dan Chak, verilerin normalde kaldırılmış bir kopyası olan önbellek tablolarını tasarlamanın bir yolunu gösterir. Sorgular hızlı çalışır ve tablonun yenilenmesi gerekmiyorsa iyi çalışır. Verileriniz uygulamanızın davranışını (örn. Uygulama durumu) kullanıyorsa, verilerin tutarsız hale getirilmesi gerektiğinden, aksi takdirde tutarsız verilerin tutarsız uygulama davranışına yol açtığını görüyorum.
Jay Godse

Denormalize edilmiş bir veri ambarı , tutarlı ve beklenen erişim yollarında büyük miktarda veri okurken kullanılabilir . Diğer tüm senaryolarda, bu tehlikeli bir yanılgıdır.
Peter Wone

2

Clarify veritabanı, birincil veya yabancı anahtarı olmayan ticari bir veritabanı örneğidir.

http://www.geekinterview.com/question_details/18869

Komik olan şey, teknik belgelerin tabloların nasıl ilişkili olduğunu, bunlara katılmak için hangi sütunları kullanacağınızı açıklamak için büyük çaba harcıyor.

Başka bir deyişle, tablolara açık beyanlarla (DRI) katılmış olabilirler , ancak yapmamayı seçtiler .

Sonuç olarak, Clarify veritabanı tutarsızlıklarla doludur ve düşük performans gösterir.

Ancak, geliştiricilerin işini kolaylaştırdığını, silmeden önce ilgili satırları kontrol etme, ekleme gibi referans bütünlüğüyle başa çıkmak için kod yazmak zorunda kalmayacağını düşünüyorum.

Ve bence bu ilişkisel bir veritabanında yabancı anahtar kısıtlamalarının olmamasının temel yararı. En azından şeytan-bakım açısından bakıldığında gelişmeyi kolaylaştırır.


Başarısız bir başvuru bütünlüğü denetimini işleyen kod, tutarsız verileri işlemek için kullanılan koddan çok daha küçüktür.
Jay Godse

@ Kabul edebilirsin! Bu yaklaşımı savunduğumu düşünmeyin.
Ed Guiness

2

Yalnızca Oracle veritabanlarını biliyorum, başkasını bilmiyorum ve yabancı anahtarların veri bütünlüğünü korumak için gerekli olduğunu söyleyebilirim. Veri eklemeden önce bir veri yapısının yapılması ve doğru hale getirilmesi gerekir. Bu yapıldığında - ve böylece tüm birincil VE yabancı anahtarlar yaratıldığında - iş yapılır!

Anlamı: öksüz satırlar? Hayýr. Bunu hayatýmda hiç görmedim. Kötü bir programcı yabancı anahtarı unutmadıkça veya başka bir düzeyde uyguladıysa. Her ikisi de - Oracle bağlamında - veri çoğaltmasına, yetim verilere ve dolayısıyla veri bozulmasına yol açacak olan büyük hatalardır. FK zorunlu olmadan bir veritabanı hayal edemiyorum. Bana kaos gibi geliyor. Unix izin sistemi gibi: herkesin kök olduğunu hayal edin. Kaosu düşünün.

Yabancı Anahtarlar, tıpkı Birincil Anahtarlar gibi önemlidir. Şöyle demek: Birincil Anahtarları kaldırırsak ne olur? Tamamen kaos olacak. İşte bu. Birincil veya yabancı anahtar sorumluluğunu programlama düzeyine taşıyamazsınız, veri düzeyinde olmalıdır.

Sakıncaları? Evet kesinlikle ! Çünkü insert üzerinde çok daha fazla kontrol olacak. Ancak, veri bütünlüğü performanstan daha önemliyse, bu bir beyinsizdir. Oracle'daki performansla ilgili sorun daha çok PK ve FK'lerle gelen dizinlerle ilgilidir.


1

Kayıtları silmeyi daha hantal hale getirebilirler - yabancı anahtarların bu kısıtlamayı ihlal edeceği diğer tablolarda kayıtların olduğu "ana" kaydı silemezsiniz. Basamaklı silme işlemleri için tetikleyicileri kullanabilirsiniz.

Birincil anahtarınızı akıllıca seçerseniz, bu değeri değiştirmek daha da karmaşık hale gelir. Örneğin, kişinin adı olarak "müşteriler" tablomun PK'sine sahipsem ve bu anahtarı "siparişler" tablosunda bir FK yaparsam, müşteri adını değiştirmek isterse, o zaman kraliyet acısıdır .. ama bu sadece çaput veritabanı tasarımı.

Fireign anahtarları kullanmanın avantajlarının sözde dezavantajlardan ağır bastığına inanıyorum.


5
Her halükarda işleri nadiren silme eğilimindeyim. Sadece "Görünür / aktif" biti işaretleyin.
Dana

+1 "Ben herhangi bir sözde dezavantajları daha ağır basar fireign tuşlarını kullanarak avantajlar inanıyoruz"
Ian Boyd

2
Birincil anahtarın değerini asla değiştiremezsiniz . Sen silmek tüm satır ve yeniden farklı bir şekilde. Eğer değiştirmeniz gerektiğini düşünüyorsanız , şemanızda hata var .
DanMan

Yabancı anahtarınız CustomerId (PK) olarak ayarlanmışsa, müşteri adını değiştirmek hiç de kolay olmaz. Siparişler tablosunda. Acı çekmenin tek yolu, FK'nin Müşteri Adı üzerine ayarlanmış olması ve asla böyle olmaması gerekir. IMHO
KeyOfJ

1

Yabancı anahtar kısıtlamalarının doğrulanması biraz CPU zaman alır, bu nedenle bazı kişiler ekstra performans elde etmek için yabancı anahtarları atlar.


6
Yinelenen ve tutarsız verileri kaldırmak için ne kadar CPU zamanı harcanır?
Ed Guiness

Evet, bu doğru. Üzerinde çalıştığım bir sistemde, bir veritabanına bir seferde 10-40 gig veri eklemeliyiz ve FK performansı ile ve olmadan FK performansı toplam zaman içinde görülebilir.
Paul Mendoza

1

Bu argümanı da duydum - yabancı anahtarlarına bir endeks koymayı unutmuş ve daha sonra belirli operasyonların yavaş olduğundan şikayet ettiler (çünkü kısıtlama kontrolü herhangi bir endeksten faydalanabilir). Özetlemek gerekirse: Yabancı anahtar kullanmamak için iyi bir neden yoktur. Tüm modern veritabanları basamaklı silmeleri destekler, bu nedenle ...


9
FK'lerin bazılarının (benim bakış açımdan) çoğu kişi tarafından kullanılmamasının asıl nedeninin, tembelliklerini performans tasarruf argümanlarıyla savunabilecekleri iddiasıyla tembellik etmeleri gerektiğine inanıyorum. Şirketimizin katlandığı Aptallık Giderinin büyük çoğunluğunun FK kısıtlamalarının uygulanmamasından ve bunun bir şirket aracılığıyla yarattığı dalgalanma etkisinden kaynaklandığına inanıyorum. Benzersiz Anahtarların eksikliği, 12 seviyeli iç içe IF'ler ve rastgele girintili 2000+ satır saklı yordamların yanında beni deli eden başka bir şey, ama şimdi duracağım.
Çad

1

Duyduğum argüman ön uçta bu iş kurallarına sahip olması gerektiğidir. Yabancı anahtarlar, ilk etapta kısıtlamalarınızı bozan herhangi bir eklemeye izin vermemeniz gerektiğinde "gereksiz ek yük ekler". Buna katılıyor muyum? Hayır, ama bunu hep duydum.

DÜZENLEME: Tahminimce, kavram olarak yabancı anahtarlardan değil, yabancı anahtar kısıtlamalarından bahsediyordu .


Hayır! Gerçek anahtarları sevmiyor!
ljs

Bu beni şaşırtıyor. Yabancı anahtar kısıtlamalarını sevmemek ile yabancı anahtarları sevmemek arasında büyük bir fark vardır. Onlar olmadan nasıl ilişkisel bir veritabanı var emin değilim.
lordscarlet

Evet, onu duyduğumda şok oldum. Ancak istemeden yanakta kalmış olabilir; belki de buraya gönderecek ve bazı aşamalarda açıklığa
kavuşacak

1

Bana göre, eğer ACID standartlarına uymak istiyorsanız , referans bütünlüğünü sağlamak için yabancı anahtarlara sahip olmak önemlidir.


1

Buradaki yorumların çoğunu ikinci yapmalıyım, Yabancı Anahtarlar, bütünlüğe sahip verileriniz olmasını sağlamak için gerekli öğelerdir. ON DELETE ve ON UPDATE için farklı seçenekler, insanların burada kullanımlarıyla ilgili olarak bahsettiği "aşağı düşmelerden" bazılarını atlamanıza olanak tanır.

Tüm projelerimin% 99'unda, verilerin bütünlüğünü güçlendirmek için FK'lere sahip olacağımı görüyorum, ancak, ne kadar kötü olduğuna bakılmaksızın, eski verilerini tutması GEREKEN müşterilere sahip olduğum nadir durumlar vardır .... ama sonra sadece geçerli veri almak için girer kod yazma çok zaman harcamak, böylece anlamsız olur.


1

Uygulama yaşam döngülerinde sürdürülebilirlik ve sabitliğe ne dersiniz? Çoğu verinin, onu kullanan uygulamalardan daha uzun bir ömrü vardır. İlişkiler ve veri bütünlüğü, bir sonraki geliştirici ekibin uygulama kodunda doğru olmasını umduğunu bırakmak için çok önemlidir. Doğal ilişkilere uymayan kirli verilerle bir db üzerinde çalışmadıysanız, göreceksiniz. Veri bütünlüğünün önemi daha sonra netleşecektir.


1

Ayrıca çoğu anahtarda yabancı anahtarların bir zorunluluk olduğunu düşünüyorum. Tek dezavantajı (zorunlu kıvama sahip olmanın getirdiği performans vuruşunun yanı sıra) yabancı bir tuşa sahip olmak, insanların işlevsel bir yabancı anahtar olduğunu varsayan kod yazmasına izin vermesidir. Buna asla izin verilmemelidir.

Örneğin, insanların başvurulan tabloya ekler kod yazdığını gördüm ve sonra ilk ekin başarılı olduğunu doğrulamadan ekler referans tablosuna ekler. Yabancı anahtar daha sonra kaldırılırsa, bu tutarsız bir veritabanıyla sonuçlanır.

Ayrıca güncelleme veya silme işleminde belirli bir davranışı üstlenme seçeneğiniz de yoktur. Yabancı anahtar bulunup bulunmadığına bakılmaksızın, istediğinizi yapmak için kodunuzu yazmanız gerekir. Silme işlemlerinin yapılmadığında basamaklı olduğunu varsayarsanız, silme işlemleriniz başarısız olur. Başvuruda bulunulan sütunlardaki güncellemelerin, olmadığı zaman başvuru satırlarına yayıldığını varsayarsanız, güncellemeleriniz başarısız olur. Kod yazma amacıyla, bu özelliklere sahip olmayabilirsiniz.

Bu özellikler açıksa, kodunuz zaten onları taklit eder ve biraz performans kaybedersiniz.

Yani, özet .... Eğer tutarlı bir veritabanına ihtiyacınız varsa yabancı anahtarlar gereklidir. Yabancı anahtarların yazdığınız kodda hiçbir zaman mevcut veya işlevsel olduğu varsayılmamalıdır.


1

Cevabı Dmitriy'nin yankısı - çok iyi koymak.

Performans hacminin sık sık getirdiği performanstan endişe duyanlar için, ekleme, silme veya güncelleme sırasında kısıtlama doğrulaması maliyet yükü olmadan FK kısıtlamasının sorgu optimize edici avantajını elde etmenin bir yolu vardır (Oracle'da). Bu, RELY DISABLE NOVALIDATE öznitelikleriyle FK kısıtlaması oluşturmaktır. Bu, sorgu eniyileyicisi veritabanı kısıtlamayı zorlamadan sorgu oluştururken kısıtlamanın uygulandığını varsaymaktadır. Burada, FK sütunlarınızda kısıtlamayı ihlal eden verileriniz olmadığından emin olmak için böyle bir FK kısıtlaması olan bir tablo doldurduğunuzda sorumluluğu üstlenmeniz konusunda çok dikkatli olmalısınız. bu FK kısıtlamasının bulunduğu tabloyu içeren sorgulardan güvenilir olmayan sonuçlar alabilir.

Bu stratejiyi genellikle veri mart şemdeki bazı tablolarda kullanıyorum, ancak entegre aşama şemde kullanmıyorum. Verileri kopyaladığım tabloların zaten aynı kısıtlamaya sahip olduğundan veya ETL yordamının kısıtlamayı uyguladığından emin olun.


1

Burada cevap veren insanların çoğu, referans kısıtlamaları ile uygulanan referans bütünlüğünün önemine çok fazla kapılıyor. Referans bütünlüğüne sahip büyük veritabanları üzerinde çalışmak iyi sonuç vermez. Oracle basamaklı silmelerde özellikle kötü görünüyor. Temel kuralım, uygulamaların veritabanını asla doğrudan güncellememesi ve saklı bir yordamla gerçekleştirilmesidir. Bu, kod tabanını veritabanının içinde tutar ve veritabanının bütünlüğünü koruduğu anlamına gelir.

Birçok uygulamanın veritabanına erişebileceği durumlarda, başvuru bütünlüğü kısıtlamaları nedeniyle sorunlar ortaya çıkar, ancak bu bir kontrole bağlıdır.

Uygulama geliştiricilerin veritabanı geliştiricilerinin bu kadar tanıdık olmayabileceği çok farklı gereksinimleri olabileceğinden çok daha geniş bir sorun vardır.


5
"uygulamalar hiçbir zaman veritabanını doğrudan güncellememeli ve saklı yordam aracılığıyla olmalıdır. Bu, kod tabanını veritabanının içinde tutar ve veritabanının bütünlüğünü koruduğu anlamına gelir." <- Burada saklı yordamlardaki mantığın veri bütünlüğünü ihlal edemeyeceğine dair bir varsayım var, ki bu tamamen yanlış.
Tim Gautier

1

Kesinlikle eminim, altında yatan bir veritabanı sistemi gelecekte değişmez, ben veri bütünlüğü sağlamak için yabancı anahtarları kullanır.

Ancak, yabancı anahtarları hiç kullanmamak için çok iyi bir gerçek hayat nedeni:

Farklı veritabanı sistemlerini desteklemesi gereken bir ürün geliştiriyorsunuz.

Birçok farklı veritabanı sistemine bağlanabilen Entity Framework ile çalışıyorsanız, "açık kaynak kodlu" ücretsiz sunucusuz veritabanlarını da desteklemek isteyebilirsiniz. Bu veritabanlarının tümü yabancı anahtar kurallarınızı desteklemeyebilir (güncelleme, satırları silme ...).

Bu farklı sorunlara yol açabilir:

1.) Veritabanı yapısı oluşturulduğunda veya güncellendiğinde hatalarla karşılaşabilirsiniz. Belki sadece sessiz hatalar olacaktır, çünkü yabancı anahtarlarınız veritabanı sistemi tarafından göz ardı edilir.

2.) Yabancı anahtarlara güveniyorsanız, iş mantığınızda veri bütünlüğü kontrolünü daha az veya hiç yapmazsınız. Şimdi, yeni veritabanı sistemi bu yabancı anahtar kurallarını desteklemiyorsa veya sadece farklı bir şekilde davranıyorsa, iş mantığınızı yeniden yazmanız gerekir.

Şunu sorabilirsiniz: Kim farklı veritabanı sistemlerine ihtiyaç duyar? Herkes, makinasında tam bir SQL Server sunucusunu karşılayamaz veya istemez. Bu, bakımı gereken bir yazılımdır. Diğerleri zaten başka bir DB sistemine zaman ve para yatırdı. Sunucusuz veritabanı, tek bir makinedeki küçük müşteriler için mükemmeldir.

Kimse, tüm bu DB sistemlerinin nasıl davrandığını bilmiyor, ancak bütünlük denetimlerine sahip iş mantığınız her zaman aynı kalıyor.


0

Her zaman onları kullanmamanın tembel olduğunu düşündüm. Bana her zaman yapılması gerektiği öğretildi. Ama sonra Joel'in tartışmasını dinlemedim. İyi bir nedeni olabilir, bilmiyorum.


Bu bir tartışmadan daha çok manşet dışı bir ifadeydi, ancak belki de konu hakkında bağımsız olarak ne düşündüğünü tam olarak araştırmalıyım! Ancak topluluğun bu konudaki görüşünü de merak ettim!
ljs

0

FK'nin bir soruna neden olabileceği bir zaman, artık anahtarın kullanılmasını istemeseniz bile, anahtara (arama tablosunda) başvuran geçmiş verilerinizdir.
Açıkçası çözüm, işleri daha iyi tasarlamaktır, ancak burada tam çözümün her zaman kontrolüne sahip olmadığınız gerçek dünya durumlarını düşünüyorum.
Örneğin: belki de customer_typefarklı müşteri türlerini listeleyen bir arama tablonuz var - belirli bir müşteri türünü kaldırmanız gerektiğini varsayalım, ancak (iş kısıtlamaları nedeniyle) istemci yazılımını güncelleyemiyor ve kimse bu durumu istila etmiyor yazılımı geliştirirken, başka bir tabloda yabancı bir anahtar olması, ona referans veren geçmiş verileri bilmenize rağmen satırı kaldırmanızı engelleyebilir.
Bu birkaç kez yanmış sonra muhtemelen db ilişkilerin icra uzakta yalın.
(Bunun iyi olduğunu söylemiyorum - sadece FK'lerden ve genel olarak db kontraksiyonlarından kaçınmaya karar verebilmeniz için bir neden belirtin)


Ne demeye çalıştığınızı anlarsam, bunun cevabının arama tablosundaki kaydı mantıksal olarak silmek veya artık alakalı olmayan geçmiş verileri arşivlemek ve arama kaydını arşivlemek olduğunu düşünüyorum.
Chad
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.