Veritabanı Normalleştirmesini ve Şema Şeffaflığını mı Tercih Ediyorsunuz?


10

Eski bir kod tabanında yeni bir gereksinim ortaya çıkmıştır, bu da temel olarak doğrudan ilişkili olmayan iki kullanıcı sınıfı arasında (tamamen farklı şemaya sahip farklı tablolarda depolanmıştır ve ne yazık ki kod neredeyse OO-farkındadır, daha az tasarlandığından ebeveyn sınıfı yoktur). Bu işlevselliği asla dikkate almayan bu eski düzene bir çanta asacağımız için, PK çarpışması olmadığının garantisi yoktur - kullanımdaki veri kümesi göz önüne alındığında, pratikte olduğu garanti edilir.

Yani, çözüm açık görünüyor: ateşle öldürün ve tüm karışıklığı yeniden yazın Bir eşleme tablosu. Haritayı uygulamanın olası yolları için iki yön aldım, ama ben bir DBA değilim, bu yüzden kaçırdığım herhangi bir artı ve eksileri olup olmadığından emin değilim.

Soyutlamayı açıklığa kavuşturmak için üç farklı kullanıcı verisi grubunu düşünün: Profesörler, Yönetim, Öğrenciler (Hayır, bu bir ev ödevi değil. Söz ver!)

Haritalama 1

(professor_id, admin_id ve student_id ilgili tablolarının yabancı anahtarlarıdır)

| mailing_id (KEY) | professor_id | admin_id | student_id | 
-------------------------------------------------------
| 1001             |     NULL     |    87    |  NULL      |
| 1002             |     123      |   NULL   |  NULL      |
| 1003             |     NULL     |   NULL   |  123       |

Bu yaklaşımın +/- eksileri üzerinde oldukça ağır görünüyor:

  • Satır başına iki "boşa" alanı
  • İhlal 2NF
  • Anormallikler eklemek / güncellemek için güvenlik açığı (yalnızca 0-1 alan NULL olarak ayarlanmış bir satır, ör.)

Profesyoneller kendi yararları olmadan değiller:

  • Haritalama tek bir arama ile gerçekleştirilebilir
  • Mailing_id'den belirli bir kullanıcı için "kaynak" verileri kolayca belirleyin

Gerçeği söylemek gerekirse, bağırsaklarımda, bu fikri hiç sevmiyorum.

Haritalama 2

(MSG_ * 'nın tanımlanmış sabitler, numaralandırma türleri veya başka bir uygun tanımlayıcı olduğunu varsayalım)

| mailing_id (KEY)  | user_type (UNIQUE1) | internal_id (UNIQUE2)| 
------------------------------------------------------------------
| 1001              | MSG_ADMIN          | 87                    |
| 1002              | MSG_PROF           | 123                   |
| 1003              | MSG_STUDENT        | 123                   |

Bu kurulum ve {user_type, internal_id} öğelerinin benzersiz bir bileşik dizini çok daha temiz hale gelir, 3NF korunur ve uygulama kodunun I / U anormalliklerini kontrol etmesi gerekmez.

Dezavantajlı olarak, DB dışında ele alınması gereken kullanıcı kaynak tablolarının belirlenmesinde, temel olarak kullanıcı_türü değerlerinin tablolarla uygulama düzeyinde eşleştirilmesine denk gelen bir miktar şeffaflık kaybı vardır. Şu anda, (oldukça güçlü bir şekilde) bu 2. haritaya doğru eğildim, çünkü olumsuz oldukça küçük.

AMA kendi sınırlamalarımın acı verici bir şekilde farkındayım ve muhtemelen her iki yönde de avantajları veya tökezleyen blokları kaçırdığımdan eminim, bu yüzden benimkinden daha akıllı zihinlere yöneliyorum.


2
Sen bulabilir rolleri Martin Fowler fikirleri ilginç bir okuma.
Marjan Venema

Gerçekten ilginçti. Ne yazık ki benim özel sorun hakkında çok fazla fikir
GeminiDomino

Yönetici olan profesörler ve yönetimde iş bulan ya da 10 yıl sonra fakülte olarak geri dönen öğrenciler alacaksınız. Muhtemelen zaten onlara sahipsiniz. Bunları ayrı tutacak mısınız yoksa birleştirmeye mi çalışacaksınız?
Elin

Roller sadece örnektir, ama amacınızı anlıyorum. Pratikte, kullanıcılar rol değiştirse bile, yine de ayrı kayıtlar olarak kalacaklardı.
GeminiDomino

İlk paragrafı yeniden ifade ederseniz harika olur. Biraz belirsiz. Demek istediğim, bir sorun olduğu açık ama ne olduğu yeterince açık değil.
Tulains Córdova

Yanıtlar:


1

İkinci fikriniz doğru olanı. Bu yaklaşım, üç çarpışan kilit alanınızı entegre etmek için yapmanız gereken tüm haritalamayı yapmanızı sağlar.

Daha da önemlisi, veritabanının bildirici kısıtlamaları kullanmanız gereken tutarlılığın çoğunu empoze etmesini sağlar .

Zaten sahip olmak istediğinizden daha fazla kodunuz var, bu nedenle entegre anahtar listenizi tutarlı tutmak için kesinlikle gerekenden daha fazla kod eklemeyin. Veritabanı motorunuzun yapması için yaptıklarını yapmasına izin verin.

Size rahatsızlık veriyor "problem çocuk" Mapping 2 olan USER_TYPEsütun. Bu sütun önemlidir çünkü INTERNAL_IDher kullanıcı türü için en fazla bir kez görünmesini sağlamak gerekir . Farkında olan herhangi bir koda ihtiyaç duyduğunuz tek zaman USER_TYPE, eşleme tablonuza ekleyip silen koddur. Bu oldukça iyi bir şekilde yerelleştirilebilir. Kodunuzda eşleme tablosu içeriğinin bulunduğu tek bir nokta oluşturacağınızı varsayalım. Bu tek noktada verinin yazıldığı fazladan bir sütun önemli değildir. Gerçekten kaçınmak istediğiniz şey, verilerin okunduğu her yere fazladan sütun eklemektir .

Alt uygulamalarınızdaki eşlemeyi kullanması gereken kod, USER_TYPEher bir alt uygulamaya, eşlemeleri tek bir uygulamaya özgü kullanıcı türüne göre filtreleyen bir görünüm vererek basitçe cahil olabilir .


3

Deneyimlerime göre tavsiyem zarafet veya 'en iyi uygulama' üzerinde tutarlılığı seçmektir. Bu, mevcut tasarımı eşleştirmek ve basit bir mailing_id, user_idalan yapısı ile ÜÇ posta tabloları (her rol için bir tane) ile eşleşmektir .

Yetersiz ama birkaç avantajı var ...

  1. Meraya çıkmadan önce bu şema üzerinde çalışacak herkes için mevcut yapının eşleştirilmesi daha kolay olacaktır.
  2. Boşa giden alanınız yok ve db'den var olmayacak şeyleri eşleştirmesini istemiyorsunuz.
  3. Çünkü her bir tablo sadece bir diğerine olacaktır ve rutinlerinizin kullanması için tüm verileri bağlayan bir görünüm oluşturmak nispeten daha kolay olacaktır.

Eminim birçok kişi bu yaklaşıma katılmayacaktır, ancak normalleştirme ve en iyi uygulamaların temel amaçları kodu daha tutarlı hale getirmektir, bu yüzden takip etmek ve hata ayıklamak daha kolaydır ... ve açıkçası tüm kod tabanını sıfırdan getirmek muhtemelen mümkün değildir.


Bu yaklaşımla ilgili sorun, veritabanının ilk etapta eşlemenin birincil amacı olan posta kimliklerinde benzersizliği zorlayamamasıdır: Aksi takdirde, her tablodan ayrı kimlik alanlarını bir "kullanıcı türü" göstergesi ile eşleştirmek herhangi bir değişiklik olmadan yapılır.
GeminiDomino

Ne elde ettiğinizi görüyorum, ancak bu tür bir sistem üzerinde çalıştıktan sonra, düşünmediğiniz bir seçenek sundum. Gördüğüm kadarıyla posta kimliği bir yere atıfta bulunmak için bazı içeriğe ihtiyaç duyacaktır (ne postalandı ya da belgeyi nasıl bulabilirim), bu yüzden posta kimliği zaten yabancı bir anahtar olmalı, bu da benzersizlik sorunlarının başka bir yerde çözülebileceği anlamına geliyor. Okuduğum gibi, bağlı olan yönetici öğrenci ve prof veri tabloları farklı yapılara sahip olabilir, bu yüzden kullanıcı türü alanı katma değer göremiyorum. Orijinal geliştiriciler bu konuyu vurmuş olmalı, ne yaptılar?
James Snell

"Kullanıcı türü" alanı, hangi tablonun söz konusu kayıtla ilişkilendirileceğini belirler. Her iki durumda da uygulama düzeyinde ele alınması gerekir ve farklı tablolarda oldukları için, yabancı anahtar kısıtlaması yapmanın iyi bir yolu yoktur. Orijinal geliştiriciler bu sorunu hiç düşünmemiş gibi görünüyor, maalesef bu yüzden bu kadar karışıklığa dönüşüyor. :)
GeminiDomino
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.