it-swarm-tr.com

Yabancı anahtarların nesi var?

İşitmeyi hatırlıyorum Joel Spolsky in podcast 014 yabancı bir anahtar kullanmış olduğunu (doğru hatırlıyorsam). Bununla birlikte, benim için veritabanınızdaki çoğaltma ve ardından veri bütünlüğü sorunlarından kaçınmak için çok hayati görünüyorlar.

İnsanların neden olduğu konusunda sağlam sebepler var mı (Yığın Taşması prensipleri doğrultusunda tartışılmaması için)?

Düzen: "Yabancı anahtar oluşturmak için bir nedenim olmadığından, bu benim ilk nedenim olabilir aslında bir tane kurmak için. "

247
ljs

Yabancı Anahtarları kullanma nedenleri:

  • orphaned Rows alamazsınız
  • tabloları otomatik olarak temizleyerek Nice "cascade silme" davranışını elde edebilirsiniz
  • veritabanındaki tablolar arasındaki ilişkileri bilmek, Optimizer’ın en etkili uygulama için sorgularınızı planlamasına yardımcı olur, çünkü birleşik kardinalite hakkında daha iyi tahminler alabilir.
  • FK'lar, veritabanında toplanacak istatistiğin en önemli olduğu konusunda oldukça büyük ipuçları veriyorlar ve bu da daha iyi performansa yol açıyor
  • her tür otomatik oluşturulmuş desteği mümkün kılarlar - ORM'ler kendilerini üretebilir, görselleştirme araçları sizin için Nice şema düzenleri oluşturabilir.
  • projede yeni olan biri işlerin akışına daha hızlı girecektir, aksi takdirde dolaylı ilişkiler açıkça belgelenmiştir.

Yabancı Anahtarları kullanmamanın nedenleri:

  • dB tutarlılığını her CRUD işleminde ekstra çalıştırıyorsunuz çünkü FK tutarlılığını kontrol etmek zorunda. Çok fazla karmaşanız varsa bu büyük bir maliyet olabilir
  • fK, ilişkileri zorlayarak, şeyleri eklemek/silmek zorunda olduğunuz ve DB'nin istediğinizi yapmayı reddetmesine yol açabilecek bir düzen belirler. (Bu gibi durumlarda, yapmaya çalıştığınız şey bir Yetimhane Satırı oluşturmaktır ve bu genellikle iyi bir şey değildir). Bu, özellikle toplu iş güncellemeleri yaptığınız zaman acı vericidir ve ikinci tablonun tutarlı bir durum yaratmasıyla bir tabloyu diğerinden önce dolduruyorsunuz (ancak ikinci yükün başarısız olması ve sizin veritabanı şimdi tutarsız mı?.
  • bazen verilerinizin kirli olacağını önceden biliyorsunuz, kabul ediyorsunuz ve DB'nin kabul etmesini istiyorsunuz.
  • sadece tembel oluyorsun :-)

Bence (belli değilim!) Çoğu yerleşik veritabanının zorunlu olmayan ve sadece biraz meta veri olan bir yabancı anahtar belirtmenin bir yolunu sağladığını düşünüyorum. İcra etmemek, FK kullanmamak için her türlü sebebi ortadan kaldırdığından, ikinci bölümdeki sebeplerden herhangi biri geçerliyse, muhtemelen muhtemelen o yola gitmelisiniz.

344
SquareCog

Bu bir terbiye sorunudur. Eğitim veya mesleki kariyerinizde bir yerde, veritabanlarını beslemek ve bakım yapmak için (veya bunu yapan yetenekli insanlarla yakın çalıştığınız) zaman harcadıysanız, varlıkların ve ilişkilerin temel ilkeleri düşünce sürecinizde iyi yerleşmiş olur. Bu kurallar arasında, veritabanınızdaki anahtarları nasıl/ne zaman/niçin belirleyeceğiniz (birincil, yabancı ve belki de alternatif olabilir). Bu ikinci doğa.

Bununla birlikte, RDBMS ile ilgili çabalarınızla geçmişinizde bu kadar kapsamlı ya da olumlu bir deneyim yaşamamışsanız, muhtemelen bu tür bilgilere maruz kalmamışsınızdır. Ya da belki geçmişiniz, ciddi bir şekilde anti-veritabanı olan bir ortama dalmayı da içeriyor (örneğin, "bu DBA'lar aptallar - biz az sayıda, birkaç Java/c # kodlu slinger seçtik"), bu durumda şiddetle karşı çıkabilirsiniz. Bazı dweeb'lerin arcane babblingsinde, FK'lerin (ve onların ima edebileceği kısıtlamaların) sadece dinlerseniz, gerçekten önemli olduğunu söyleyenlere.

Herkesin çocukken dişlerini fırçalamanın önemli olduğu öğretildi. Onsuz geçebilir misin? Elbette, ama çizginin aşağısında bir yerde, her yemekten sonra fırçalanmış olsaydı, elinden daha az dişi olacak. Anneler ve babalar, veritabanı tasarımını ve ağız hijyenini kapsayacak kadar sorumlu olsaydı, bu konuşmayı yapmazdık. :-)

79
Ed Lucas

Bundan kurtulabileceğiniz birçok uygulama olduğuna eminim, ama bu en iyi fikir değil. Veritabanınızı düzgün bir şekilde yönetmek için uygulamanıza her zaman güvenemezsiniz ve açık bir şekilde veritabanını yönetmek uygulamanız için çok fazla endişe verici olmamalıdır.

Bir ilişkisel veritabanı kullanıyorsanız, o zaman bazı ilişkiler içinde tanımlanmış olmanız gerekir. Ne yazık ki bu tutum (yabancı anahtarlara ihtiyacınız yoktur) veri bütünlüğü gibi saçma sapan şeylerle rahatsız edilmek istemeyen birçok uygulama geliştiricisinin benimsemiş gibi görünmektedir (ancak şirketlerin kendilerine özel veritabanı geliştiricileri olmadığı için). Genellikle bu türlerin bir araya getirdiği veritabanlarında, yalnızca birincil anahtarlara sahip olduğunuz için şanslısınız;)

52
AlexCuse

Yabancı anahtarlar gerekli ilişkisel veritabanı modellerine göre.

40
Galwegian

Onları hep kullanırım ama sonra finansal sistemler için veri tabanları oluştururum. Veri tabanı, uygulamanın kritik bir parçasıdır. Finansal bir veritabanındaki veriler tam olarak doğru değilse, kod/ön uç tasarımınıza ne kadar çaba gösterdiğiniz önemli değildir. Sadece zamanını boşa harcıyorsun.

Aynı zamanda, çoklu sistemlerin genellikle doğrudan veritabanıyla arayüzlenmesi gerektiği gerçeği de var - veriyi okuyan diğer sistemlerden (Crystal Reports) veri ekleyen sistemlere (mutlaka tasarladığım bir API kullanarak değil); VBScript'i yeni keşfeden ve SQL kutusu için SA parolasına sahip donuk örgülü yönetici). Eğer veritabanı mümkün olduğu kadar salak geçirmez değilse, güle güle veritabanı.

Verileriniz önemliyse, evet, yabancı anahtar kullanın, verilerle etkileşime girmek için saklı yordamlar paketi oluşturun ve yapabileceğiniz en zor DB'yi yapın. Verileriniz önemli değilse, neden başlamak için bir veritabanı hazırlıyorsunuz?

29
Ant

Güncelleme : Artık her zaman yabancı anahtarları kullanıyorum. "Karmaşık testler" itirazına cevabım "ünite testlerinizi" yazmasıdır, böylece veritabanına hiç ihtiyaç duymazlar. Veritabanını kullanan tüm testler uygun şekilde kullanmalı ve yabancı anahtarlar içermelidir. Kurulumu yapmak için daha az acı verici bir yol bulun. "


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

Yabancı anahtar kullandığınızı varsayalım. "Bir finansal hesabı güncellediğimde işlemin kaydını kaydetmesi gerektiğini" yazan otomatik bir test yazıyorsunuz. Bu testte, yalnızca iki tabloyla ilgileniyorsunuz: accounts ve transactions.

Ancak, accounts, contracts için yabancı bir anahtara sahip ve contracts, clients için fk değerine sahip ve clients, cities, ve cities, states için bir fk değerine sahiptir.

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

Bu konuda en az iki olası bakış açısı var:

  • “Bu iyi bir şey: Testiniz gerçekçi olmalı ve bu veri kısıtlamaları üretimde var olacaktır.”
  • “Bu kötü bir şey: Sistemin diğer parçalarını dahil etmeden test parçalarını 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 .

19
Nathan Long

"Kayıtları silmeyi daha zahmetli hale getirebilirler - yabancı anahtarların bu kısıtlamayı ihlal ettiği diğer tablolarda kayıtların bulunduğu" ana "kaydı silemezsiniz."

SQL standardının bir yabancı anahtar silindiğinde veya güncellendiğinde gerçekleştirilecek eylemleri tanımladığını hatırlamak önemlidir. Tanıdıklarım:

  • ON DELETE RESTRICT - Diğer tablodaki bu sütunda anahtar bulunan satırların silinmesini önler. Ken Ray'in yukarıda tanımladığı şey buydu.
  • ON DELETE CASCADE - Diğer tablodaki bir satır silinirse, bu tablodaki referans alan satırları silin.
  • ON DELETE SET DEFAULT - Diğer tablodaki bir satır silinirse, sütunun varsayılan değerine başvuran yabancı anahtarları ayarlayın.
  • ON DELETE SET NULL - Diğer tablodaki bir satır silinirse, bu tabloya başvuran yabancı anahtarları null değerine ayarlayın.
  • ON DELETE NO ACTION - Bu yabancı anahtar yalnızca yabancı bir anahtar olduğunu gösterir; yani OR mappers'ta kullanım içindir.

Bu aynı işlemler ON UPDATE için de geçerlidir.

Varsayılan, hangi sql sunucuyu kullandığınıza bağlı gibi görünüyor.

14
Powerlord

@ imphasing - bu tam olarak bakım kabuslarına neden olan zihniyet türüdür.

Neden oh, verinin garantili en azından tutarlı olması için en iyi ihtimalle zayıf bir önleyici tedbir olan "yazılım zorunluluğu" olarak adlandırılan en azından tutarlı olması için bildirimsel referans bütünlüğünü göz ardı ettiniz.

14
Ed Guiness

Bunları kullanmamak için iyi bir neden var: Eğer rollerini veya nasıl kullanacaklarını anlamıyorsanız.

Yanlış durumlarda, yabancı kilit kısıtlamalar kazaların şelale çoğaltılmasına neden olabilir. Birisi yanlış kaydı kaldırırsa, geri almak bir mamut görevi haline gelebilir.

Ayrıca, tersine, bir şeyi çıkarmanız gerektiğinde, zayıf tasarlanmışsa, kısıtlamalar sizi engelleyen her türlü kilitlemeye neden olabilir.

12
Kent Fredric

Hiç bir iyi sebep yok yok onları kullanmak için ... artık satırlar sizin için önemli değil sanırım .

11
Matt Rogish

Daha büyük soru şudur: gözleri bağlı bir şekilde sürerken? 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şikliklerinde ilgili mantıksal varsayımların, mantığın kendisinin yeniden şekillendirilebileceğini unutmayın. Genel olarak, veritabanlarındaki kısıtlamalar, belirli mantıksal iddialar ve varsayımlar için görünüşte doğru olan, çağdaş mantıksal varsayımlar altında yerine getirilir.

Bir uygulamanın yaşam döngüsü boyunca, referans ve veri kontrolleri, özellikle yeni gereklilikler mantıksal uygulama değişikliklerini yönlendirdiğinde, uygulama aracılığıyla polis veri toplamasını kısıtlar.

Bu listenin konusuna - yabancı bir anahtar kendi başına "performansı iyileştirmez" veya gerçek zamanlı işlem işleme sistemi açısından önemli ölçüde "performansı düşürmez". Ancak, YÜKSEK hacimli "toplu iş" sisteminde kısıtlama kontrolü için toplu bir maliyet vardır. Yani, burada fark, gerçek zamanlı vs toplu işlem süreci; toplu işlem - sıralı olarak işlenen bir partinin kısıtlama kontrolleri tarafından tahakkuk eden maliyetin, performans artışı yarattığı durumlarda.

İyi tasarlanmış bir sistemde veri tutarlılığı kontrolleri bir partiyi işlemeden "önce" (yine de burada bir maliyet de vardır); bu nedenle, yükleme sırasında yabancı anahtar kısıtlama kontrolleri gerekli değildir. Aslında, yabancı anahtar dahil tüm kısıtlamalar, toplu işlenene kadar geçici olarak devre dışı bırakılmalıdır.

QUERY PERFORMANS - tablolar yabancı anahtarlara katılırsa, yabancı anahtar sütunlarının İNDEKSİZ OLMAMASI (ilgili birincil anahtarın tanımlamaya göre dizine eklenmesine rağmen) olduğunun farkında olun. Bir yabancı anahtarı dizine sokmak, bunun için herhangi bir tuşu dizine almak ve dizine alınmış tablolara katılarak, dizinde dizine alınmamış bir tuşa yabancı anahtar kısıtlamasıyla katılmak yerine, daha iyi performanslarda yardımcı olur.

Denekleri değiştirme, eğer bir veritabanı sadece web sitesi gösterme/oluşturma içeriğini/etc ve tıklama tıklamalarını destekliyorsa, o zaman tüm tablolarda tam kısıtlamaları olan bir veritabanı bu tür amaçlar için öldürülür. Bunu düşün. Çoğu web sitesi bunun için bir veritabanı bile kullanmaz. Verilerin sadece kaydedildiği ve söylenilen referans alınmadığı benzer gereksinimler için, kısıtlamaları olmayan bir bellek içi veritabanı kullanın. Bu, veri modelinin olmadığı, evet mantıksal modelin olmadığı, fiziksel veri modelinin olmadığı anlamına gelmez.

4
jasbir L

Tecrübelerime göre, Veritabanı Kritik Uygulamalarında FK kullanmaktan kaçınmak her zaman daha iyidir. Burada FK’ların iyi bir uygulama olduğunu söyleyen erkeklerle aynı fikirde değilim, ancak veritabanının çok büyük olduğu ve büyük CRUD işlemleri/sn olduğu pratik değil. İsim vermeden paylaşabilirim ... en büyük yatırım bankalarından biri veritabanlarında tek bir FK bulunmuyor. Bu kısıtlamalar, DB içeren uygulamalar yaratılırken programcılar tarafından yönetilir. Temel neden, 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 olmayacak, ancak bununla uğraşırken çok büyük bir gecikme yaratır. herhangi bir büyük bankanın günlük işler olarak yapması gereken toplu işlem.

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

3
Rachit

"Bir kayıt eklemeden önce, ilgili bir kaydın başka bir tabloda olup olmadığını kontrol edin" iş mantığıdır.

İşte bunu veritabanında istememek için bazı nedenler:

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

  2. Veritabanını değiştirmek, değişiklikleri üretim havuzuna iterek bir yazılım düzeltmesini dağıtmak kadar kolay değildir. Veri tabanı yapısını mümkün olduğunca değiştirmekten kaçınmak istiyoruz. Ne kadar çok iş mantığı varsa, veritabanında databae'yi değiştirme ihtiyacı duyma şansınızı o kadar arttırırsınız (ve yeniden indekslemeyi tetikler).

  3. TDD. Birim testlerinde veritabanını alaylarla değiştirebilir ve işlevselliğini test edebilirsiniz. Veritabanınızda herhangi bir iş mantığınız varsa, tam bir test yapmıyorsunuz ve ya veri tabanı ile test etmeniz ya da iş mantığını sınama amacıyla kodla çoğaltmanız, mantığı çoğaltmanız ve çalışma mantığının çalışma olasılığını artırmaması gerekiyor. aynı şekilde.

  4. Mantığınızı farklı veri kaynaklarıyla yeniden kullanma. Veritabanında mantık yoksa, uygulamam veritabanındaki kayıtlardan nesneler oluşturabilir, bunları bir web hizmetinden, bir json dosyasından veya başka bir kaynaktan oluşturabilir. Sadece veri haritalayıcı 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 kontrollere ihtiyacınız var. Veritabanında mantık yoksa, uygulamayı farklı veritabanı veya düz dosya uygulamaları kullanarak farklı konumlara dağıtabilirim.

3
Tom B

Yabancı Anahtarları Kullanmak İçin Ek Sebep: - Bir veritabanının daha fazla tekrar kullanılmasını sağlar

Yabancı Anahtarları Kullanmamanın Ek Nedeni: - Yeniden kullanımı azaltarak bir müşteriyi aracınıza kilitlemeye çalışıyorsunuz.

3
Dan

Veri tutarlılığı sağlamak için yararlı olduklarından önceki cevapları kabul ediyorum. Ancak, birkaç hafta önce normalize edilmiş ve tutarlı verilerin artılarını ve eksilerini tartışan Jeff Atwood tarafından ilginç bir yazı vardı.

Birkaç kelimeyle, denormalize edilmiş bir veri tabanı, büyük miktarda veri ile çalışırken 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 daha dikkatli olmaya zorlar.

2

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

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

İşin komik yanı, teknik belgelerin tabloların nasıl ilişkili olduğunu, bunlara katılmak için hangi sütunları kullanacağını vb. Açıklamak için çok uzun sürüyor.

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

Sonuç olarak, Clarify veritabanında tutarsızlıklar var ve performans düşük.

Ancak, geliştiricilerin işlerini kolaylaştırdığını, silmeden önce ilgili satırları kontrol etmek, eklemek, eklemek gibi referans bütünlüğü ile baş etmek için kod yazmak zorunda kalmayacağını düşünüyorum.

Ve bence, ilişkisel bir veritabanında yabancı anahtar kısıtlamaları olmamasının asıl yararı budur. Geliştirmeyi kolaylaştırır, en azından şeytan bakışı açısından.

2
Ed Guiness

Sadece Oracle veritabanlarını biliyorum, başkaları yok ve Foreign Keys'in veri bütünlüğünü korumak için gerekli olduğunu söyleyebilirim. Veri girmeden önce bir veri yapısının yapılması ve doğru yapılması gerekir. Bu yapıldığında - ve böylece tüm birincil VE yabancı anahtarlar oluşturulur - iş yapılır!

Anlamı: artık satırlar? Hayır. Hayatımda hiç görmedim. Kötü bir programcı yabancı anahtarı unutmazsa ya da başka bir seviyede uygularsa. Her ikisi de - Oracle bağlamında - veri çoğaltmasına, Yetim verisine ve dolayısıyla veri bozulmasına yol açacak çok büyük hatalar. FK zorlama olmadan bir veritabanı düşünemiyorum. Bana kaos gibi geldi. Biraz Unix izin sistemine benziyor: herkesin kök olduğunu hayal edin. Kaosu düşün.

Yabancı Anahtarlar, Birincil Anahtarlar gibi çok önemlidir. Şöyle demek: Birincil Anahtarları çıkarırsak ne olur? Peki, toplam kaos olacak. İşte bu. Birincil veya yabancı anahtar sorumluluğunu programlama seviyesine taşıyamazsınız, veri seviyesinde olmalıdır.

Dezavantajları? Evet kesinlikle ! Çünkü girişte, çok daha fazla kontrol gerçekleşecek. Ancak, veri bütünlüğü performanstan daha önemliyse, bu hiç akıllıca olmaz. Oracle'daki performans sorunu, PK ve FK'larla birlikte gelen endekslerle daha fazla ilgilidir.

2
tvCa

Kayıtları silmeyi daha zahmetli 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.

Ana anahtarınızı akıllıca seçmezseniz, bu değeri değiştirmek daha da karmaşık hale gelir. Örneğin, "müşteri" masamın PK'sini kişinin adı olarak alırsam ve bu anahtarı "siparişler" masasında "FK" yaparsam, müşteri adını değiştirmek isterse, o zaman kraliyet acısı olur. ama bu sadece ayakkabılı veritabanı tasarımı.

Fireign tuşlarını kullanmanın avantajlarının sözde dezavantajlara göre daha ağır basacağına inanıyorum.

1
Ken Ray

Buradaki yorumların çoğunu ikinci yapmak zorundayım, Yaban Anahtarları bütünlük bilgisine sahip olmanızı sağlamak için gerekli öğelerdir. ON SİLME ve GÜNCELLEME için farklı seçenekler, insanların kullanımlarıyla ilgili burada bahsettiği "düşme düşüşlerinin" bazılarını aşmanızı sağlar.

Tüm projelerimin% 99'unda, verilerin bütünlüğünü uygulamak için FK'lara sahip olacağımı biliyorum, ancak ne kadar kötü olduğuna bakılmaksızın eski verilerini TUTMAK gereken müşterilere sahip olduğum nadir durumlar var. ama sonra yine de geçerli verileri almak için girilen kodları yazmak için çok zaman harcıyorum, bu yüzden anlamsız hale geliyor.

1
Mitchel Sellers

Duyduğum argüman, ön uçta bu iş kurallarına sahip olması gerektiğidir. Yabancı anahtarlar, "ilk etapta kısıtlamaları kıran hiçbir eke izin vermemeniz gerektiğinde" gereksiz ek yük ekleyin ". Buna katılıyor muyum? Hayır, ama her zaman duyduğum şey bu.

EDIT: Benim tahminim, bir kavram olarak yabancı anahtarları değil yabancı anahtar kısıtlamalarını kastettiğidir.

1
lordscarlet

Yabancı anahtar kısıtlamalarını doğrulamak biraz CPU zaman alır, bu nedenle bazı insanlar daha fazla performans almak için yabancı anahtarlar çıkarır.

1
remonedo

Gelecekte değişmeyecek olan temel veritabanı sisteminin değişmeyeceğinden eminseniz, veri bütünlüğünü sağlamak için yabancı anahtarları kullanırdım.

Fakat burada yabancı anahtarları hiç kullanmamak için çok iyi bir gerçek hayat sebebi daha var:

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

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

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üvenirseniz, işletme mantığınızda veri bütünlüğü kontrollerini daha az veya hiç yapamazsınız. Şimdi, eğer yeni veritabanı sistemi bu yabancı anahtar kuralları desteklemiyorsa veya sadece farklı bir şekilde davranıyorsa, iş mantığınızı yeniden yazmak zorundasınız.

Sorabilirsiniz: Kim farklı veritabanı sistemlerine ihtiyaç duyar? Eh, herkes kendi makinesinde tam gelişmiş bir SQL Server alamaz ya da istemez. Bu, korunması gereken bir yazılımdır. Diğerleri zaten başka bir DB sistemine zaman ve para yatırdı. Sunucusuz veritabanı sadece bir makinedeki küçük müşteriler için mükemmeldir.

Hiç kimse, bu DB sistemlerinin nasıl davrandığını bilmiyor, ancak iş mantığınız, bütünlük kontrolleri ile daima aynı kalıyor.

1
Michael

Ben Dmitriy tarafından cevap yankı - çok iyi koymak.

Performans ek yükü FK'larının sık sık getirdiği konulardan endişe edenler için, (Oracle'da), ekleme, silme veya güncelleme sırasında kısıtlama validasyonunun maliyet yükü olmadan, FKK kısıtlamasının sorgu optimizatörü avantajını elde etmenin bir yolu vardır. Bu, RELY DISABLE NOVALIDATE niteliklerine sahip FK kısıtı oluşturmaktır. Bu, sorgu iyileştirici ASSUMES sorguları oluştururken kısıtlamanın uygulandığı, veritabanı gerçekten kısıtlamayı zorlamadığı anlamına gelir. FK sütunlarınızda, kısıtlamayı ihlal eden verilerinizin olmadığından kesinlikle emin olmak için, bunun gibi bir FK kısıtlaması olan bir tabloyu doldururken sorumluluk almak için çok dikkatli olmalısınız. FK kısıtının açık olduğu tabloyu içeren sorgulardan güvenilir olmayan sonuçlar alabilir.

Bu stratejiyi genellikle data mart şemalarımdaki bazı tablolarda kullanırım, ancak entegre aşama şemamda kullanmıyorum. Verileri kopyaladığım tabloların zaten uygulanan aynı kısıtlamaya sahip olduğundan veya ETL yordamının kısıtlamayı zorladığından emin olun.

1
Mike McAllister

Bu argümanı ben de duydum - yabancı anahtarlarına bir endeks koymayı unutan ve sonra bazı işlemlerin yavaş olduğundan şikayet etti (kısıtlama kontrolü herhangi bir endeksten yararlanabileceğinden). Özetle: Yabancı anahtar kullanmamak için iyi bir sebep yoktur. Tüm modern veritabanları basamaklı silmeleri destekler, yani ...

1
Arno

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

1
CodeRot

Buraya cevap verenlerin çoğu, referans kısıtlamaları yoluyla uygulanan referans bütünlüğünün önemine fazla kapılıyor. Referans bütünlüğü ile büyük veritabanları üzerinde çalışmak sadece iyi performans göstermiyor. Oracle, basamaklı silme işlemlerinde özellikle kötü görünüyor. Temel kuralım, uygulamaların hiçbir zaman veritabanını doğrudan güncellememesi ve saklı bir yordam aracılığıyla olması gerektiğidir. Bu, kod tabanını veritabanında tutar ve veritabanının bütünlüğünü koruduğu anlamına gelir.

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

Uygulama geliştiricilerin, veritabanı geliştiricilerin mutlaka aşina olmaları gerekmeyecekleri için çok farklı gereksinimleri olabilir.

1
Zak

Ayrıca yabancı anahtarların çoğu veritabanında bir gereklilik olduğunu düşünüyorum. Tek dezavantajı (tutarlılık sağlamakla gelen performans vuruşunun yanı sıra) yabancı bir anahtara sahip olmanın, insanların işlevsel bir yabancı anahtara sahip olduğunu varsayan bir kod yazmasına izin vermesidir. Buna asla izin verilmemeli.

Örneğin, insanların başvurulan tabloya ekleyen bir kod yazdığını gördüm ve sonra ilk ekleme işleminin başarılı olduğunu doğrulamaksızın referanslama tablosuna ekler eklemeye çalışır. Yabancı anahtar daha sonra kaldırılırsa, bu tutarsız bir veritabanına neden olur.

Ayrıca güncelleme veya silme işleminde belirli bir davranış üstlenme seçeneğiniz de yoktur. Yabancı bir anahtar olup olmadığına bakılmaksızın, istediğinizi yapmak için hala kodunuzu yazmanız gerekir. Silmeyin, silmeyin, olmadığında basamaklandırılmış olduğunu varsa, silmeniz başarısız olur. Başvurulan sütunlara yönelik güncellemeler, olmadıklarında başvuru satırlarına yayılırsa, güncellemeleriniz başarısız olur. Kod yazma amacıyla, bu özelliklere sahip olamayabilirsiniz.

Bu özellikler açıksa, kodunuz yine de bunları taklit edecektir ve küçük bir performans kaybedersiniz.

Yani, özeti .... Tutarlı bir veritabanına ihtiyacınız varsa yabancı anahtarlar gereklidir. Yabancı anahtarların, yazdığınız kodda asla mevcut veya işlevsel olduğu varsayılmamalıdır.

1
Eric

Wowowo ...
Her yere cevap verir. Aslında bu şimdiye kadar karşılaştığım en karmaşık konu. FK'ları ihtiyaç duyulduğunda kullanırım ama üretim ortamında nadiren kullanırım.

İşte nadiren Fks kullandığım nedenlerim:

1. Performansı arttırmak için çoğu zaman küçük sunucudaki büyük verilerle uğraşıyorum. FK'ları kaldırmam gerekiyor. Çünkü FK’larınız varsa ve RDBMS’yi Yaratın, Güncelleyin ya da Sildiğinizde ilk önce kısıtlama ihlali olup olmadığını ve çok büyük bir DB’niz olup olmadığını ölümcül olabilecek bir şey olup olmadığını kontrol edin.

2. Bazen başka yerlerden veri almam gerekiyor ve ne kadar iyi yapılandırıldıklarından emin olamadığım için FK’leri bırakıyorum.

3. Birden fazla DB ile uğraşıyorsanız ve başka bir DB'de referans anahtarına sahipseniz, FK'leri kaldırana kadar (şu anki gibi) iyi gitmeyecek (veritabanı ilişkileri arası)
4. Aynı zamanda, ne RDBMS ne olursa olsun ya da DB'nizin herhangi bir RDBMS sistemine ihraç edilmesini ve ithal edilmesini istediğiniz bir uygulamayı yazdığınızda, bu durumda her bir RDBMS sisteminin kendi FK'leriyle ilgilenmek için kendine özgü bir yolu vardır ve muhtemelen FK'ların kullanımını bırakmak zorunda kaldılar.

5. Eğer RDBMS platformunu (ORM'ler) kullanıyorsanız, bazılarının tekliflerinin çözümüne ve teknikliğine bağlı olarak kendi haritalarını sunduğunu ve masaları ve FK'lerini oluşturmayı umursamadığınızı biliyorsunuz.

6. Son noktadan önce, FK'lara sahip DB ile başa çıkma bilgisi ve FK 7'ye ihtiyaç duymadan tüm İşleri yapan bir uygulama yazma bilgisine sahip olacaksınız. Son olarak, her şeyin senaryoya bağlı olduğunu söylemeye başladım. Bir engel. Her zaman elde edebileceğin en iyinin en iyisini yapmak isteyeceksin!


Herkese teşekkürler!

Bir FK'nin size bir soruna neden olabileceği bir zaman, artık anahtarın kullanılabilir olmasını istemeseniz de, anahtara başvuran geçmiş verilere (arama tablosunda) sahip olmanızdır.
Belli ki çözüm her şeyi daha iyi tasarlayabilmek, fakat burada her zaman tam çözümü kontrol edemediğiniz gerçek dünya durumlarını düşünüyorum.
Örneğin: belki de farklı müşteri türlerini listeleyen customer_type arama masanıza sahipsiniz - belirli bir müşteri türünü çıkarmanız gerektiğini söyleyelim, ancak (iş kısıtlamaları nedeniyle) yapamazsınız istemci yazılımını güncelleyin ve yazılımı geliştirirken hiç kimsenin bu durumu görmediği, başka bir tabloda yabancı bir anahtar olduğu gerçeği, onu referans alan tarihsel verileri bilmeseniz bile, satırı kaldırmanızı engelleyebilir.
Bununla birkaç kez yandıktan sonra muhtemelen ilişkilerin uygulanmasından uzaklaşıyorsunuz.
(Bunun iyi olduğunu söylemiyorum - sadece genel olarak FK ve db çelişkilerinden kaçınmaya karar vermeniz için bir neden vermek)

0
hamishmcn

Üzerinde çalıştığım bir projede, açık ilişkilerden ziyade çoğu zaman örtük oluyordu, böylece aynı sütunda sayısız tablo birleştirilebiliyordu.

Aşağıdaki tabloyu al

Adres

  • Adres Kimliği (PK)
  • ENTITYID
  • EntityType
  • Kent
  • Durum
  • Ülke
  • Vb..

EntityType'ın olası değerleri Çalışan, Şirket, Müşteri olabilir ve EntityId, ilgilendiğiniz tablodaki primarky anahtarını belirtir.

Bunun bir şeyler yapmanın en iyi yolu olduğunu sanmıyorum ama bu proje için işe yaradı.

0
Curtis

Birçok şey gibi, bu bir tradeoff. Veri bütünlüğünü doğrulamak için işi nerede yapmak istediğinize ilişkin bir soru:

(1) yabancı bir anahtar kullanın (bir tabloyu yapılandırmak için tek bir nokta, özellik zaten uygulanmış, test edilmiş, işe yaramış)

(2) veri tabanını kullanıcılara bırakın (aynı tabloları güncelleyen olası birden fazla kullanıcı/uygulama, testte potansiyel olarak daha fazla başarısızlık noktası ve artan karmaşıklık anlamına gelir).

Veritabanının yapması daha verimli (2), bakımı daha kolay ve (1) ile daha az riskli.

0
Jen A

Dmitriy’in söylediklerini tekrarlayacağım, ama bir noktaya ekleyerek.

30'dan fazla masaya büyük satır setleri eklemek için gereken toplu faturalandırma sistemi üzerinde çalıştım. Bir veri pompası (Oracle) yapmamıza izin verilmedi, bu yüzden toplu ekler yapmak zorunda kaldık. Bu tablolarda üzerlerinde yabancı anahtarlar vardı, ancak zaten onların hiçbir ilişkiyi bozmadıklarından emin olduk.

Eklemeden önce, yabancı anahtar kısıtlamalarını devre dışı bırakırız; böylece Oracle, ekleri sonsuza kadar sürmez. Ekleme başarılı olduktan sonra kısıtlamaları yeniden etkinleştiririz.

Not: Tek bir kayıt için birçok yabancı anahtar ve alt satır veri içeren büyük bir veritabanında, bazen yabancı anahtarlar kötü olabilir ve basamaklı silmelere izin vermemek isteyebilirsiniz. Faturalama sistemindeki bizler için çok uzun sürüyor ve basamakları siliyor olsaydık veritabanına çok fazla vergi harcıyorduk, bu yüzden rekoru ana sürücü (ebeveyn) tablosundaki bir alanla kötü olarak işaretliyoruz.

0
typicalrunt

DB2'de, MQT'ler (Materyalize Sorgu Tabloları) kullanılıyorsa, optimizer'ın verilen herhangi bir sorgu için doğru planı seçmesi için yabancı anahtar kısıtlamaları gerekir. Öncelik bilgisini içerdiklerinden, optimize edici bir MQT kullanmak veya kullanmamak için meta verileri yoğun olarak kullanır.

0
Senthil

Veri yapısı tasarımının iyi bir prensibi, bir tablonun veya nesnenin her niteliğinin iyi anlaşılmış bir kısıtlamaya tabi olmasını sağlamaktır. Bu önemlidir, çünkü siz veya programınız veritabanındaki geçerli verilere güvenebilirseniz, kötü verilerden kaynaklanan program hataları yaşama ihtimaliniz daha düşüktür. Ayrıca, hata koşullarını işlemek için kod yazmak için daha az zaman harcıyorsunuz ve hata işleme kodunu önceden yazma olasılığınız daha yüksek.

Çoğu durumda bu kısıtlamalar derleme zamanında tanımlanabilir; bu durumda, niteliğin daima aralık dahilinde kaldığından emin olmak için bir filtre yazabilir veya niteliği kaydetme girişiminin başarısız olmasını sağlayabilirsiniz.

Bununla birlikte, çoğu durumda bu kısıtlamalar çalışma zamanında değişebilir. Örneğin, başlangıçta "kırmızı", "yeşil" ve "mavi" değerlerini alan bir özellik olarak "renkli" olan "arabalar" tablonuz olabilir. Programın yürütülmesi sırasında bu ilk listeye geçerli renkler eklemek mümkündür ve eklenen yeni "arabalar" güncel renkler listesindeki herhangi bir rengi alabilir. Ayrıca, genellikle bu güncellenmiş renk listesinin bir program yeniden başlatılmasından sonra hayatta kalmasını istersiniz.

Sorunuzu cevaplamak için, çalışma zamanında değişebilecek veri kısıtlaması için bir gereksiniminiz varsa ve bu değişikliklerin bir program yeniden başlatılmasından sonra hayatta kalması gerekiyorsa, yabancı anahtarlar soruna en basit ve özlü çözümdür. Geliştirme maliyeti, bir tablonun eklenmesidir (örneğin "renkler", "otomobiller" tablosuna yabancı bir anahtar kısıtlama ve bir indeks) ve çalışma süresi maliyeti, güncel renkler için ekstra tablo aramasıdır Verileri doğrulamak ve bu çalışma zamanı maliyeti genellikle endeksleme ve önbellekleme ile azaltılır.

Bu gereksinimler için yabancı anahtar kullanmazsanız, listeyi yönetmek için yazılım yazmalı, geçerli girişlere bakmalı, diske kaydetmeli, liste büyükse verileri verimli bir şekilde yapılandırmalı, listedeki hiçbir güncellemenin yapılmamasını sağlayın Liste dosyasını bozabilir, birden fazla okuyucu ve/veya yazar olması durumunda listeye seri erişim sağlayabilirsiniz. yani, bir çok RDBMS işlevselliği uygulamanız gerekir.

0
Jay Godse

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

0
Kilhoffer

Q uite sık sık hata alıyoruz FK kısıtlamaları Bir alt satır eklenemiyor veya güncellenemiyor: bir yabancı anahtar kısıtı başarısız oluyor İki envanter_source ve sözleşme_ satırı tablosu olduğunu varsayalım ve Inventory_source (- === -) Contrac_lines içindeki envanter_source_id Envanter_source'dan envanterde varız ve kaydın envanter_source'den kaydını silmek istediğimizi ve kaydın sözleşme_line içinde bulunduğunu veya PK sütununu silmek istediğimizi varsayalım. Base tablosundan FK kısıtlamaları için hatalar alıyoruz, aşağıda not edilen adımları kullanarak bunu önleyebiliriz.

CREATE TABLE inventory_source (
inventory_source_id int(11) NOT NULL AUTO_INCREMENT,
display_name varchar(40) NOT NULL,
state_id int(11) NOT NULL,
PRIMARY KEY (inventory_source_id),
KEY state_id (state_id),
CONSTRAINT ba_inventory_source_state_fk FOREIGN KEY (state_id) REFERENCES   ba_state (state_id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

CREATE TABLE contract_lines(
contract_line_id int(11) NOT NULL AUTO_INCREMENT,
inventory_source_id int(11) NULL ,
PRIMARY KEY (contract_line_id),
UNIQUE KEY contract_line_id (contract_line_id),
KEY AI_contract_line_id (contract_line_id),
KEY contract_lines_inventory_source_fk (inventory_source_id),
CONSTRAINT contract_lines_inventory_source_fk FOREIGN KEY       (inventory_source_id) REFERENCES ba_inventory_source (inventory_source_id)
) ENGINE=InnoDB AUTO_INCREMENT=135 DEFAULT CHARSET=utf8 ;

Aşağıdaki adımları kullanarak üstesinden gelebiliriz: -

  1. Envanteri_source'dan satırı silmek veya güncellemek, sözleşme_line tablosundaki eşleşen satırları otomatik olarak silecek veya güncelleyecektir ve bu, kademeli silme veya güncelleme olarak bilinir.
  2. Bunu yapmanın başka bir yolu, sözleşme_line tablosundaki envanter_source_id sütununu, NULL olarak ayarlamaktır, buna karşılık gelen kayıt envanter_source tablosunda silinir.
  3. Ana tabloyu silmek veya güncellemek için kısıtlayabiliriz, başka bir deyişle envanter_source tablosu için silme veya güncelleme işlemini reddedebiliriz.
  4. Başvurulan tabloda ilgili bir yabancı anahtar değeri varsa, bir birincil anahtar değerini silme veya güncelleme girişimi devam etmesine izin verilmez.
0
Vikas Kukreti