2010-02-05 8 views
9

Katıldığım bir projenin baş geliştiricisi, ilgili satırları silmek için kaskadlara güvenmenin kötü bir uygulama olduğunu söylüyor.Yabancı anahtar basamaklarına güvenmek kötü mü?

Bunun nasıl kötü olduğunu göremiyorum, ancak eğer/neden olduğu hakkındaki düşüncelerinizi bilmek istiyorum.

+0

Olası çoğaltılabilir [Ne zaman/Neden SQL Server'da Cascading kullanmak için?] (Http://stackoverflow.com/questions/59297/when-why-to-use-cascading-in-sql-server). Ayrıca, diğer soruların cevaplarıyla çok daha fazla katılıyorum, ki buradakilerden oldukça farklı. –

cevap

14

Bunu nadiren satırları dönem sildiğimi söyleyerek başlayacağım. Genelde tutmak istediğiniz çoğu veri. Sadece silinmiş olarak işaretlendiğinden, kullanıcılara gösterilmeyecek (yani silinmiş gibi görünecektir). Tabii ki, kullanıcı sepetini boşalttığında kayıtların silinmesi, verilere ve bazı şeylere (alışveriş sepeti içerikleri gibi) bağlıdır.

Yalnızca buradaki sorunun, silmek istemediğiniz kayıtları istemeden silebileceğinizi varsayabilirim. Bununla birlikte, referans bütünlüğü bunu önlemelidir. Öyleyse, bu durum karşısında açıkça bir sebep göremiyorum.

+0

Yasal veya gerçek kapasite sorunu olmadıkça, burada cletus ile aynı fikirdeyim. Depolama o kadar ucuz ve hızlı ki bu günlerde zor bir silme yapmak için nadiren gerçek bir neden var. +1 –

+4

İşte bir neden var - birisi bir "AND DELETED = 0" unuttu çünkü silinen veri, sorgu sonuçlarına geri sürünme. Bunu yaparsanız, tüm silinmiş verileri yalnızca canlı verilere yönelik bir görünüm veya benzer bir şekilde arkasına gizleyin ya da ** sorunla karşılaşırsınız. –

+0

@Michael - Mimarinize bağlı olarak, örneğin bir linq projem var ve T4 şablonlarında '.Current()' uzantı metodu çağrısını 'DataContext.GetTable ' ürettiği referanslara eklemenin önemsiz. Bunun diğer durumlarda nasıl bir sorun olacağını görebilirdim, ama * her zaman *. –

5

Basamaklı silme kullanmam. Niye ya? Çünkü bir hata yapmak çok kolay. İstemci açıkça silmek uygulamaları (ve FK kayıtlarını sevk silme gibi silinmesi için şartları yerine.) Aslında

gerektirecek çok daha güvenli, silme başına silindi olarak kayıtları işaretleme veya içine taşıyarak önlenebilir arşiv/tarih tabloları. SELECT s yaklaşık (sadece% 10'dan daha az takdirde kullanılacak 'isDeleted = false' bir dizin filtre uygulamak zorunda kalacak beri silindi olarak kayıtları işaretlenmesi durumunda

, o, silinen veri olarak işaretlenmiş nispi oranda bağlıdır Kayıtların RDBMS'ye bağlı olarak silinmiş olarak işaretlenir. Bu 2 senaryo

hangisini tercih edersiniz:

1) Geliştirici size gelir "Hey, bu işe yaramaz sil" diyor. İkiniz de ona bakıp, yanlışlıkla tüm masa içeriğini silmeye çalıştığını anlıyorsunuz. İkinizin de gülüşleri var ve yaptığınız şeye geri dönün.

2) Geliştirici size gelir ve koyunca "Yedeklerimiz var mı?" Diye sorar.

+0

Ne zamandan beri önemsiz verileri siliyordunuz? Önemsiz veriler genellikle statiktir. Bu argüman su tutmaz. –

+0

Diyelim ki sistemden bir sipariş veriyoruz: Sipariş -> Satır Öğeleri -> Yorumlar. Siparişi (doğal olarak uygulamada onay istemi) silersem, diğer 2 tablodaki satırlar artık işe yaramaz. Ebeveyn kaydını kurtarmak için kurulum yapmıyorsanız (ki bu durumda, silmiyorsunuzdur ...) genellikle çocuklar artık önemli değil, daha sonra hepsini tek bir veritabanında silip atmaktan çok kolay bir şekilde başlıyor. Söylediğim gibi, uygulama ve fikir meselesi, ama ** onların kullanımları var. –

+0

+1 "Yedeklememiz var mı?"" – Neolisk

10

En azından sürpriz ilkeyi uyguladığınızı söyleyebilirim.

Basamaklı silmeler beklenmeyen veri kaybına neden olmamalıdır. Bir silme ilgili kayıtların silinmesini gerektiriyorsa ve kullanıcının bu kayıtların gideceğini bilmesi gerekiyorsa, basamaklı silmeler kullanılmamalıdır. Bunun yerine, kullanıcının ilgili kayıtları açıkça silmesi veya bir bildirim sağlaması gerekir. Diğer taraftan, tablo geçici nitelikte başka bir tabloyla ilişkiliyse veya ana varlık yok olduğunda hiçbir zaman gerekmeyecek kayıtlar içeriyorsa, basamaklı silme işlemleri tamam olabilir.

Bu, numaralı yönergeleri, kasıtlı silme işlemlerine güvenmek yerine koddaki ilgili kayıtları silerek açık bir şekilde'u kullanmayı tercih ettiğimi söyledi. Aslında, aslında hiçbir zaman ilgili kayıtları gizli bir şekilde silmek için basamaklı bir silme kullanmamıştım. Ayrıca, cletus tarafından açıklandığı gibi yumuşak bir silme kullanırım.

+0

Bu iyi bir prensip, doğal olarak ortaya çıkan sürprizler var - bunlardan daha fazlasını üretmeye gerek yok. – Rawheiser

1

Basamaklı silmelerden kaçınmanın bir başka büyük nedeni performanstır. Ana tablodan 10.000 kayıtları silmeniz gerekene kadar iyi bir fikir gibi görünüyor, bu da çocuk masalarında milyonlarca kayıt var.Bu silmenin boyutu göz önünde bulundurulduğunda, tüm masayı saatlerce belki de günlerce tamamen kilitlemek olasıdır. Bunu neden riske atacaksın? Bir kayıt silindiri silmek için on dakika daha az zaman harcanması kolaylık sağlamak için silme silme silme işlemleri silinsin mi?

Ayrıca, bir alt kayıt içeren bir kaydı silmeye çalıştığınızda elde ettiğiniz hata genellikle iyi bir şeydir. Bu kaydı silmeyi istemediğinizi, eğer bunu yaparsanız kaybedeceğiniz bir veri olduğunu belirtiyor. Cascade silme işlemi, geçmişte siparişleri olan bir müşteriyi sildiyseniz, örneğin siparişlerle ilgili bilgi kaybıyla sonuçlanan çocuk kayıtlarını siler ve silecektir. Bu tür bir şey, mali kayıtlarınızı iyice dağıtabilir.

+0

İlk senaryonuzu anlamıyorum. Alternatif yükü ortadan kaldıracak alternatif iş nasıl olurdu?" çocuk kayıtları mı yoksa bir şekilde silme sorunu neden olan tabloları kilitler mi ve ayrı silmeler bunu engeller mi? –

+0

Yığınları alt kümelerdeki grup tablolarından ve daha sonra ana silmeden yaparsınız. Bir üretim Enterprise türü veritabanında kademeli silme kullanımı hiç .Bir üretim soruna neden olması çok muhtemeldir. – HLGEM

+0

Silinmesi gereken birçok satır durumunda (başvurulan tabloda), eğer varsa, basamaklı silmelerin performansı daha iyi, kodunuz DB'deki hızdan daha hızlı çalışmayacak. Diğer senaryo bana garip geliyor - referenc'i "yanlışlıkla" silemezsiniz satırlar. Bir FK'yi basamaklı olarak ilan ettiyseniz, başvurulan satırların başvuru sahibi olmadan var olmasına izin vermemeniz anlamına gelir, bu da tamamen kabul edilebilir bir durumdur. –

0

Aynı şekilde basamaklı silmelerin kötü bir uygulama olduğu söylendi ... ve bu yüzden onları kullanan bir müşteriye rastlamadan onları asla kullanmayın. Onları neden kullanmam gerektiğini gerçekten bilmedim ama tüm FK kayıtlarını da silmeden kodlamak zorunda kalmamaları için çok uygun olduklarını düşündüm. Bu yüzden neden bu kadar "kötü" olduklarını araştırmaya karar verdim ve şu ana kadar bulduğum şeyden, onlar hakkında sorunlu bir şey görünmüyorlar. Aslında şimdiye kadar gördüğüm tek iyi argüman, performans hakkında yukarıda belirtilen HLGLEM. Ama genellikle bu kayıtların çoğunu silmediğim için çoğu durumda bunları kullanmanın iyi olacağını düşünüyorum. Tüm seçenekleri düşündüğümden emin olmak için başkalarının kullanabileceği diğer argümanları duymak isterim.

+1

Silme çağrısı ile ilgili sorun, başvurulan tablodaki bir değeri yanlışlıkla silerseniz, bu değeri kullanan tüm satırlar silinir (yalnızca bu satırlardaki değer değil, tüm satır). Gerçekten aptal görünüyor, ama bunu bugün zor yoldan öğrendim. – Holonaut

+0

@Holonaut Senin söylediklerini görüyorum, bu bir problem olur. Ancak, bir kaydı programatik olarak yanlışlıkla sildiyseniz ve genellikle düğmenin tıklanmasıyla ortaya çıkan aynı sorunu görüyorum. –