Bir veritabanı tablosunda "kayıt durumu" sütununa sahip olmak kötü bir uygulama mı?


12

Ben durumu sütunu olduğunu ilk açıklamak zorunda değil bir durumunu yansıtacak şekilde tasarlanan gerçek dünya öğesi tablosunda kaydındaki (satırındaki) tarafından temsil etti. Aksine, kaydın kendisinin durumunu göstermesi amaçlanmıştır.

Etkin / Etkin değil veya Onaylanmış / Silinmiş / Kilitli / Beklemede / Reddedilmiş vb. Gibi karmaşık olabilir. Durum, bir boole / kısa tamsayı sütununda veya tek karakterli bir sütunda, true/ 1= Etkin veya A= Onaylandı.

Temel fikir, uygulamada bir geri dönüşüm kutusu / çöp benzeri kurtarma desteğine sahip olmak (ve veritabanında simüle etmek). Bir kullanıcının kayıtları "silmesine" izin verebilecek bir ön uç GUI veya başka bir arabirim varsa, tablodaki kaydı gerçekten silmez, ancak kayıt durumunu Etkin Değil veya Silindi olarak değiştirir. Arabirim kayıtları aldığında, yalnızca durumun Etkin veya Onaylı olduğu koşuluyla eşleşen kayıtları alır.

Kullanıcı bir hata yaparsa ve "silinen" kaydın (kullanıcı perspektifinde) kurtarılması gerekiyorsa, bir DBA kaydı kolayca Aktif veya Onaylı hale getirebilir; bu da yedekleri aramaktan ve umarım orijinal kaydı bulmaktan daha iyi olur Orada. Veya arayüzün kendisi, kullanıcının silinen kayıtları ayrı bir görünümde görüntülemesine ve gerektiğinde geri yüklemesine veya hatta kalıcı olarak silmesine (gerçek kaydı silme) izin verebilir.

Sorularım:

  • Bu iyi bir uygulama mı yoksa kötü bir uygulama mı?
  • Verilerin normalleştirilmesini etkiler mi?
  • Potansiyel tuzaklar nelerdir?
  • Aynı hedefe ulaşmak için alternatif bir yöntem var mı? (notu gör)
  • Veritabanında yalnızca belirli bir durum için veriler üzerinde benzersiz kısıtlamalar uygulanmasını nasıl sağlayabilirsiniz (ancak diğer durumlar için herhangi bir sayıda kopyaya izin verebilirsiniz)?
  • Neden veritabanları yerel olarak "geri dönüşüm kutusu" benzeri bir özellik veya tablo izleme / kurtarma sağlamaz, böylece arabirimlerin endişelenmeden gerçek kayıtları silmesine izin verebiliriz?

Not: Ayrı bir geçmiş tablosu tutmayı okudum, ancak depolama ve tetikleyiciler oluşturmak ve tetikleyicileri izlenen tablonun şemasıyla güncel tutmak zorunda olmaktan daha kötü görünüyor.


Benzersiz kısıtlamalarla (zaten adlandırdığınız) sorun, geçmiş tablolarının neden genellikle tercih edileceğidir - benzersiz anahtar kısıtlamalarını orijinal tablolarda tutabilir ve bunları geçmiş tablosuna ekleyemezsiniz. belirli (DB'ye bağlı) depolama seçeneklerini kullanmak için , depolama açısından genellikle daha iyidir , daha da kötüsü değildir. Bu tabloların birçoğuna sahip olduğunuzda, tetikleyiciler ve geçmiş tabloları elle yazılmamalı, üretilmeli, bu da onları nasıl "güncel" tutabilecekleri sorunu çözecektir.
Doc Brown

Yanıtlar:


5

Bunu "Yumuşak Sil" olarak biliyorum; gerçekten olmasa da bir kaydı "silindi" olarak işaretlemek.

Bu iyi bir uygulama mı yoksa kötü bir uygulama mı?

Değişir.
Bu, kullanıcılarınızın [çok] ihtiyaç duyduğu bir şeyse, muhtemelen iyi bir şeydir. Bununla birlikte, vakaların büyük çoğunluğunda, az fayda için [çok fazla] ek yük olduğunu iddia ediyorum.

Verilerin normalleştirilmesini etkiler mi?

Hayır, ama olacak bu verilerin sizin Endekslemeyi etkiler.
Bu satırların sorgularınızda olabildiğince erken hariç tutulması için dizinlerinize "silinmiş" sütununu eklediğinizden emin olun.

Potansiyel tuzaklar nelerdir?

Verileriniz biraz daha karmaşık hale geliyor. Verilerin yakınında herhangi bir yere giden her şeyin bu ekstra, "orada olmayan" kayıtlar hakkında "bilmesi" gerekir. Veya, bu satırları hariç tutan tablolarda Görünümler oluşturmanız ve bu görünümleri, örneğin Raporlama Seçim Aracınızda kullanmanız gerekir.

Veritabanınızın boyutu artabilir. Bu satırları gerçekten silmiyorsanız, o zaman hala oradalar, yer kaplıyorlar. Bu, özellikle dizinlerinize eklediğiniz için sorun olabilir veya olmayabilir, bu nedenle tükettikleri alan çoğalır.

Aynı hedefe ulaşmak için alternatif bir yöntem var mı? (notu gör)

Gerçekten değil, hayır.

Veritabanında yalnızca belirli bir durum için veriler üzerinde benzersiz kısıtlamalar uygulanmasını nasıl sağlayabilirsiniz (ancak diğer durumlar için herhangi bir sayıda kopyaya izin verebilirsiniz)?

Kolayca değil. Beyan Edici Referans Bütünlüğü (yabancı anahtar maddeler) bunu uygulamanın en temiz yoludur ve Raporlama araçları gibi şeylerin tablolar arasındaki ilişkileri belirlemek için bu kurallardan faydalanması kolaydır. Bu tür kurallar, "statü" ne bakılmaksızın tüm kayıtlar için geçerlidir (ve bunun için bir yol yoktur).

Alternatif olarak, tablolar arasındaki referans bütünlüğünü uygulayan ve ihtiyacınız olan tüm akıllı, koşullu şeyleri yapan yordamsal kod parçacıkları olan Tetikleyiciler kullanmaktır. Bu sizin durumunuz için iyidir, ancak Deklaratif RI'nin faydalarının çoğu pencereden dışarı çıkar - tablolarınız arasında [dışarıdan] saptanabilir bir ilişki yoktur; tetikleyicilerin hepsi "gizli".

Neden veritabanları yerel olarak "geri dönüşüm kutusu" benzeri bir özellik veya tablo izleme / kurtarma sağlamaz, böylece arabirimlerin endişelenmeden gerçek kayıtları silmesine izin verebiliriz?

Neden ki ?

Sonuçta bunlar dosya sistemleri veya elektronik tablolar değil, veritabanlarıdır.

Yaptıkları, çok, çok iyi yapabilirler.

Yapmadıkları şey, muhtemelen çok fazla talep edilmedi.


İyi yanıt, ancak alternatif seçenekler var, örneğin satırları kurtarabileceğiniz bir yedekleme tablosuna taşıyın. Yedekleme tablosunda en az dizin olabilir. Bu, mevcut yaklaşımla not ettiğiniz sorunları en aza indirir (daha büyük dizin, tablonun kullanıcıları için olası karışıklık vb.), Ancak açık bir şekilde, bakım yapmak için başka bir tablonuz olduğu gerçeğini ekler (ve girişlerin yabancı anahtar referanslarına gittiği anlamına gelir). Oldukça birkaç seçenek daha var - ama akla gelenlerin hepsi bazı özel uygulamalardır, bu tür durumlar için her SQL veritabanı tarafından sağlanan genel bir şey değildir.
Frank Hopkins

9

Bu bir uygulama. İyi ya da kötü olup olmadığı büyük ölçüde uygulamanıza ve ne kadar sıklıkla bir "silme işlemini geri almanız" gerekeceğine / yapmak istediğinize bağlıdır. Sistemdeki her tablonun bu tür sütunlarını koymak için bir plandan oldukça şüpheliyim - sistemdeki her tabloya silme işlemini uygulamaktan rahatsız olmanız pek olası görünmüyor. Ve uygulama gerektirir - vakaların büyük çoğunluğunda, tek bir tablodan tek bir satır silme işlemi yapmıyorsunuz, satırları silen ve ilgili tabloları güncelleyen alt tablolarda dolaşmanız gerekiyor.

Geri kalan soruların çoğu için, yüksek oranda uygulamaya bağlıdır. Örneğin, Oracle bir tablodaki tüm değişiklikleri izlemek için farklı yöntemler sunar - Flashback Veri Arşivi (Toplam Geri Çağırma olarak da bilinen FDA), bir satırın her sürümünün tam geçmişini ve uygulama için veritabanı içi arşivlemeyi korumak için en yeni yaklaşımdır. yumuşak silme düzeni. Diğer veritabanları, kalıbın uygulanması için başka yollar sağlayabilir. Veritabanına ve yumuşak silme işlemini nasıl uyguladığınıza bağlı olarak, performans, kısıtlamaların uygulanıp uygulanamayacağı ve nasıl uygulanabileceği gibi çeşitli etkiler olacaktır. Oracle'dan bahsediyorsak, işleve dayalı dizinlerle çok şey yapabilirsiniz. , SQL Server'da benzer amaçlar için genellikle filtrelenmiş dizinler kullanabilirsiniz.


Oracle Flashback tam olarak istediğim şey için ideal bir çözüm. Oracle'ın tescilli olması çok kötü.
ADTC

4

MRP / ERP sistemlerinde "silinmek üzere işaretlendi" alanının kullanılması çok yaygındır.

Örneğin, artık etkin olmayan olarak satılan bir parça veya envanter kaydını işaretlemek isteyebilirsiniz, ancak yine de ilişkili emirler vardır. Kayıtta gerçek bir silme işlemi yapılması, henüz gönderilmemiş siparişleri, henüz gönderilmemiş defter girişlerini, ay sonuna kadar oluşturulmayacak geçmiş tablolarını vb. Etkileyebilir. Birçok sistem, bir seri geçmedikçe kayıt silme işlemine izin vermez diğer tablolara karşı doğrulamaların sayısı. İlişkileriniz aracılığıyla silme işlemlerini basamaklıyorsanız, gerçek bir silme daha da yıkıcı olabilir.

Bunun yerine, silinmek üzere işaretleyerek, kayda net bir niyet işareti koyarsınız ve daha sonra zamanlanmış bir görev, ilgili tüm tabloların artık başvurmadığını doğrularsa kaydı silebilir.

Benzer bir durum, bir müşteri tablosunda ve diğer "uzun vadeli" tablolarda bu özellik için yapılabilir. Bayrağın adı "gönderildi" veya "iptal edildi" gibi bir şey haline gelse de, siparişler gibi daha değişken tablolarda bile mantıklı. Aynı işlevi yerine getirir: bu saniyeyi silmeyin, ancak temizleme programı için bir bayrak olarak kullanın, böylece gelecekte kaydın silinmesini doğrulamaya çalışır.


3

Alternatif bir çözüm olarak, olay kaynağının kullanımı tablo yapısını karmaşıklaştırmadan benzer hedeflere izin verir, ancak verilerinizi biraz daha karmaşık hale getirir, çünkü değişikliği bir olay geçmişine devam edebilecek bir olaya yazmanız gerekir. . Bu, daha sonra herhangi bir zamanda olduğu gibi veritabanını yeniden oluşturmanıza izin verir, bu da çok kullanışlı bir özellik olabilir.

(Değiştirilen veya silinen kayıtları değiştirmeden önce başka bir tabloya kopyalamak istediğinizi düşündüğünüz "geçmiş tablosu" ile kastettiğinizin bu olduğuna inanmıyorum)


İlginç bir kavram. Bunun nasıl uygulanabileceğine bakacağım.
ADTC

1

Bu modeli bu kullanım durumları için sık sık görüyorum ve kullanıyorum:

  • yalnızca bugün geçerli olan değerleri görüntülemek istediğiniz meta veriler. Örneğin, etkinleştirilen = 1 olan bir açılır listede otomobil üreticileri listesinden seçim yapmak için ID, VALUE, ENABLED tablo değerleri 1, 'Ford', 1 ve 2, 'Edsel', 0, 3, 'Toyota' , 1 yalnızca Ford ve Toyota'nın seçeneklerini sunar
  • paradigmanın bir vakanın bir seferde sadece bir durumda olabileceği bir vaka yönetim sistemi için. Bu durumda, geçiş sütunu, kontrol kısıtlamaları tarafından uygulanan 0 veya 1 değerleriyle CURRENT olarak adlandırıldı. Bir durum bir durumdan diğerine geçerken uygulama eski durumun CURRENT bayrağını 0 ve yenisine günceller 1

Sorun, tablolara birden fazla uygulama veya web hizmeti yazıyorsa veri bütünlüğünü zorlamaktır. Bir vaka için sadece bir tane mevcut durumun olmasını nasıl sağlarsınız? Justin Cave'in işaret ettiği gibi, bu, Oracle'da bir işleve dayalı sanal bir dizin oluşturarak yapılabilir, ancak başlangıçta basit bir kavram gibi görünen şey için bu ek yük.


1

Verilerinizi raporlama için kullanmayı planlıyorsanız iyi bir uygulamadır (yeterince büyük bir uygulamanın raporları olması gerekir).

Uygulamanızı hızlandırmak için, raporlama araçlarının veritabanınızda çalışmasına gerçekten izin vermemelisiniz. Bu nedenle, başka bir veritabanına kopyala / senkronize etmeniz gerekir.

Kullandığım recordStatussadece iki devletin ACTIVEya CANCELLEDbir kombinasyon halinde lastUpdatedOndamgası. Genellikle iş anlamında recordStatusolanlardan ziyade kullanıyorum status.

Raporlama veritabanını uygulama ile senkronize ederken lastUpdatedOn, raporlama tarafında hangilerini değiştireceğimi bilmek için bir filtre yapıyorum.

Raporlama tarafında recordStatusveya lastUpdatedOnalanlarına sahip olmayacağım çünkü genellikle rapor edilmeyecek. Bu nedenle bir CANCELLEDdurum gördüğümde, kaydı raporlayan taraftan yalnızca etkin kayıtları olacak şekilde silerim.

Bu, neredeyse tam senkronizasyonun gerekli olduğu arşivler veya yedeklemeler gibi diğer mağaza türlerine genişletilebilir. Ancak, raporlama daha yaygın bir amaçtır.

Senin örneğini Not Approved, New, Pendingo anlamda iş akıllı yapar yere sadece gitmeli bunu anlamına gelen bir iş olduğu gibi ortak bir alan olarak koymak için iyi bir fikir değil.

Kilitli olarak, versionNokaydınız için iyimser bir kilit sağlayan kullanın .

Yerine bir başka seçenek recordStatusolduğunu recordActiveve bir olarak sakladığınız booleanhangi az yer ve daha az indeksleme kaplıyor, ama tahmin olmayabilir gelecekteki ihtiyaçları endişe olacaktır.

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.