Konfigürasyon verileri: tek satırlı tabla vs. ad-değer çifti tablosu


64

Diyelim ki kullanıcı tarafından yapılandırılabilecek bir uygulama yazdınız. Bu "konfigürasyon verisi" ni bir veritabanına depolamak için yaygın olarak iki desen kullanılır.

  1. Tek sıralı tablosu

      CompanyName  |  StartFullScreen  |  RefreshSeconds  |  ...
    ---------------+-------------------+------------------+--------
      ACME Inc.    |        true       |       20         |  ...
    
  2. Ad-değer çifti tablosu

      ConfigOption   |   Value
    -----------------+-------------
     CompanyName     | ACME Inc.
     StartFullScreen | true (or 1, or Y, ...)
     RefreshSeconds  | 20
     ...             | ...
    

Her iki seçeneği de vahşi doğada gördüm ve her ikisinin de bariz avantajları ve dezavantajları var, örneğin:

  • Tek satırlı tablolar, sahip olabileceğiniz yapılandırma seçeneklerinin sayısını sınırlar (çünkü bir satırdaki sütunların sayısı genellikle sınırlıdır). Her ek yapılandırma seçeneği, bir DB şema değişikliği gerektirir.
  • Bir ad-değer çifti tablosunda her şey "sıkıca yazılmıştır" (Boolean / Date / etc parametrelerinizi kodlamanız / kodunu çözmeniz gerekir).
  • (daha birçok)

Kalkınma topluluğu içinde hangi seçeneğin tercih edilebileceği konusunda fikir birliği var mı?


2
'Dikey' yaklaşımın farklı veri türlerine sahip olmasının bir nedeni yoktur. Her satıra bir int, float ve metin sütunu ekleyin. 'SaveConfigInt (' field ', n)'
GrandmasterB

4
Bunu soran mükemmel bir StackOverflow sorusu var ve en üstteki cevap her iki yaklaşıma da artılar ve eksiler veriyor. stackoverflow.com/questions/2300356/…
Kevin

1
Yaklaşım 3: JSON veya YAML gibi basit bir veri değişim formatına sahip Tek Sütun / Tek Sıra. Her iki yaklaşımın da avantajlarını birleştirir.
schlamar

<config> <CompanyName> ACME Inc. </CompanyName> <StartFullScreen> true </StartFullScreen>20<RefreshSeconds></RefreshSeconds> </config> gibi xml / json içeren karmaşık verilerle tek satırlık tablo kullanmaya ne dersiniz? iş katmanındaki nesneyi doğrula?
John

1
@John: Hiyerarşik yapılara ihtiyaç duyulursa iyi fikir. Olmazlarsa, sadece karmaşıklığı olan seçenek 2'dir.
Heinzi,

Yanıtlar:


15

Kişisel olarak çoğu şey için tek satırlı masaları tercih ederim. Daha az esnek olduğu doğru olsa da, dinamik davranış beklemiyorsanız, daha sonra gerekirse ekstra sütunlar eklemek tamamen kabul edilebilir. Bir bakıma, programlama sırasında sınıf üyelerine sahip olan isim-değer çiftlerini tutmak için bir sözlük / harita kullanmanın karşılığıdır. Verilen, mükemmel bir metafor değil, ancak bir çok avantaj ve dezavantajı düşündüğünüzde paraleldir.

Yani sınıf üyeleri üzerinde bir sözlük / harita kullanır mısın? Temsil edilecek veri miktarını bir ad-değer çift tablosuna sahip olmak gibi tamamen uyarlanabilir olduğunu düşünmek için bir nedeniniz olmadıkça, muhtemelen değil.


Saklanacak veriler kullanıcı tanımlıysa ne olur? yani, kullanıcının alan etiketini, tutacağı veri türünü belirterek bir "alan" oluşturabileceği bir kullanıcı arayüzü düşünün. Bu, DDL ifadelerinin koddan çalıştırılması anlamına gelir. Hala seçenek 1 ile gider misiniz?
devanalyst

1
@devanalyst Hayır, eğer veriler bileşenden bileşene değişebilseydi, onu temsil etmek için statik bir tablo oluşturmaya çalışmak mantıklı olmazdı. Bu durumda ikinci seçeneği kullanmak daha iyi olacaktır.
Neil

12

Genelde seçenek 2 ile giderdim, ancak veri türünü zorlamak için birden fazla sütuna sahip olurdum

ConfigOption   |   textValue    |   DateValue   |   NumericValue

Seçenek 1 Bir ActiveSütun ekleyerek tüm Konfigürasyonları kolayca "değiştirebilmeniz" için Ek Avantaj'a sahiptir .


Yapılandırmaların devre dışı bırakılmasına izin verecekseniz (seçenek 1 için), en azından bir activatedOnzaman damgası yapın, böylece ne zaman etkinleştirildiğini anlayabilirsiniz . Ve eğer seçenek 2 ile gidecekseniz ... değerleri birden çok sütuna (veya oracle, nerede (görünüşe göre) boş ve boş bir dizgenin eşdeğeri) saklaması halinde ne olur ?
Clockwork-Muse

1
@ X-Zero, Çoklu Yapılandırmaların saklanması genellikle test amaçlı yapılır, ancak zaman damgası zarar görmez. Yapılandırma Bakım, değeri almak için çağrı hangi sütunu kontrol edeceğini bilir, gerçekten isterseniz, veri türü için bir sütun ekleyebilirsiniz .. Ama bence bitti ...
Morons

5
bir EATV (Varlık-Özniteliği-Türü-Değeri) şeması üçüncü normal formu keser; Tür sütunu, Tür sütununun tanımladığı Değer sütunu yoluyla, yalnızca tablonun birincil anahtarıyla dolaylı olarak ilişkilidir. Ek olarak, dinamik tip depolama ve örnekleme çok fazla çözmez; Bir GetConfigValue () yöntemi herhangi bir tür döndürebiliyorsa, çalışma zamanında hala değerlendirilmesi gereken Object (veya bir şekilde beklenen tür verilecek) vermelidir.
KeithS

5
Gördüğüm yazılımda her zaman seçenek 1 uygulandı, seçenek 2'ye dönüştürülmek zorunda kaldı. Seçenek 2 zaman içinde bakımı daha kolay, sadece ilk kez doğru bir şekilde uygulamak için daha fazla zaman alıyor. Seçenek 1'in uygulanması hızlı ve kolaydır, ancak yazılımınız büyüme şansı olmadan küçük olmadıkça zamanla bakım korkunçtur.
Jimmy Hoffa

8

Benim için, tek sıraya mı yoksa EAV'ye mi gitmek, onları nasıl tüketmek istediğinize bağlı.

EAV'ın gücü, yapıda değişiklik yapılmadan yeni verilerin eklenebilmesidir. Bu, yeni bir yapılandırma değeri istiyorsanız, tabloya eklemeniz ve kodda istediğiniz yere çıkarmanız anlamına gelir ve etki alanına, şemaya, eşleştirmeye, DAL sorgularına yeni bir alan eklemeniz gerekmez , vb.

Buradaki kusur, kötümser verilerle uğraşmanızı gerektiren sadece en iyi yapıya sahip olmasıdır. Herhangi bir konfigürasyon değerinin her kullanımı, değerin bulunmamasını veya uygun formatta olmamasını beklemeli ve olmadığında buna göre davranmalıdır. Bir yapılandırma değeri bir çift veya bir int veya karakter ile ayrıştırılamaz. Boş olabilir. değer için hiç satır olmayabilir. Bunun etrafındaki yollar genellikle belirli bir kod içi türdeki tüm yapılandırma değerleri için varolan tek bir geçerli "varsayılan" değer gerektirir ( çok nadirdir; daha sık varsayılan değer, hiç yok gibi kod tüketmek için sorunludur) veya varsayılan değerlerin sabit kodlu sözlüğünü saklayın (her yeni sütun eklendiğinde değişmesi gerekir, bu da EAV depolamasının birincil avantajını oldukça değiştirir).

Tek bir geniş satır hemen hemen tam tersidir. Bunu, varolan her yapılandırma değeri için bir alan / özellik içeren bir Configuration nesnesinin tek bir örneğiyle eşlersiniz. Bu değerlerin derleme zamanında ne tür olması gerektiğini tam olarak biliyorsunuz ve eğer bir yapılandırma sütunu mevcut değilse veya uygun tipte bir değer yoksa, DAL'de "hızlıca başarısız oluyorsunuz", istisnaları yakalamak için size bir yer veriyor yapılandırma alımı / hidrasyon sorunları.

Başlıca dezavantaj, her yeni değer için yapısal bir değişimin gerekli olmasıdır; yeni DB sütunu, DAL'deki yeni sütun (eşleme veya SQL sorguları / SP'ler), yeni etki alanı sütunu, kullanımı düzgün bir şekilde test etmek için gerekli.

Bunlardan herhangi birinin kullanılacağı uygun durum, dezavantajların azaltıldığı durumdur. Benim için, config kodlamasının çoğu durumu tek satırlı bir uygulama için çağrıda bulundu. Bunun temel nedeni, programınızın bir bölümünün davranışını düzenleyen tamamen yeni bir yapılandırma değeri tanıtıyorsanız , yeni yapılandırma değerini kullanmak için kodu zaten değiştirmeniz gerekir ; neden yapılandırma nesnesine uğrayıp değil eklemek kullanılacak değeri?

Kısacası, yapılandırmayı depolamak için bir EAV şeması gerçekten çözmeyi düşündüğü sorunu çözmez ve sundukları sorunların çözümünde çoğu DRY'yi ihlal eder.


3

Özellikle yapılandırma değerleri için şunu söyleyebilirim - tek sıra ile gidin. Şu anda geliştirme sürecinden geçmediğiniz sürece, bu sütunlar ne sıklıkla değişecek?

Büyük (r) sürümleri arasında kapalı kalma süresinde sahip olamayacağınız genişletilebilirlik kodundan ziyade değerlerin veri tipini güvence altına almak muhtemelen en iyisidir . Ayrıca, tek bir sütunu eklemek veya kaldırmak, var olan en kolay göç ile ilgilidir. Yeni bir yapılandırma seçeneği oluştururken başım ağrıyor.

Ek olarak, "kullanıcılar" un bir başlık vermeden bu seçenekleri yapılandırabileceğini söylediniz. Kullanıcı başına yapılandırmalar mı? Öyleyse, yapılandırma seçeneklerinin sütunlarda olması gerektiğini daha güçlü bir şekilde savunacağım - kullanıcı başına tek bir satır. Daha sonra birçok bakım baş ağrısından kurtulacaktır.


2

Müşterileriniz JSON parçalarını işleyebiliyorsa (bu yalnızca diziler ve sözlükler değil, aynı zamanda düz dizeler, sayılar, boolean'ler, boş değerler değil), seçenek adı ve JSON içeren bir dize değeri içeren çok satırlı bir tablonuz olabilir. Bu ayrıca yapılandırılmış değerleri saklamanıza izin verir ve bunları işlemek için gereken kod zaten orada olmalıdır.

Müşterileriniz JSON parçalarını işleyemiyorsa, yeni müşteriler edinin.


1

Tek sıra Artıları: İyi tanımlanmış. Eksileri: Yapılandırmayı değiştirmek bir ağrı olabilir. DB göçleri vb.

Varlık Değer Artıları: Süper esnek, yapılandırmanızı geliştirmeyi destekler. Eksileri: Referans bütünlüğü? Özelliği üzerinde bir şey yapmadan önce var olup olmadığını görmek için kodunuzda daha fazla kontrol.

Mongo gibi ilişkisel olmayan bir db tarafından desteklenen yaklaşım 2'yi alırdım. Emin olabileceğiniz bir şey varsa, onun değişmesi.


1

İkisini de kullan!

Hangi seçeneklerin birden fazla örneği olabileceğini ve hangi seçeneklerin genel olduğunu sıralayın.

Tek sıralı tablo (yapılandırmalar)

  id  |  company_name  |  start_fullscreen  |  refresh_seconds  |  ...
------+----------------+--------------------+-------------------+-------
  4   |  ACME Inc.     |  true              |  20               |  ...

İsim-değer-çift tablosu (seçenekler)

  name             |  value          | update_time  
-------------------+-----------------+--------------
  generic_option_1 |  Option 1 Value | timestamp    
  generic_option_2 |  Option 2 Value | timestamp    
  generic_option_3 |  Option 3 Value | timestamp    
  configuration    |  4              | timestamp    
  ...              |  ...            | ...          

Bunun daha esnek olduğunu düşünüyorum.

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.