Veri Tabanı Tasarımında İmkansızlığın Artırılması


26

Joshua Bloch'un Etkili Java'sındaki öğelerden biri, sınıfların örneklerin mümkün olduğunca az ve tercihen hiçbir şekilde mutasyona izin vermesi gerektiği düşüncesidir.

Çoğu zaman, bir nesnenin verileri bir biçimde bir veritabanına devam eder. Bu, özellikle daha büyük bir sistemdeki tek bir varlığı temsil eden tablolar için, bir veri tabanındaki değişmezlik fikrini düşünmeme neden oldu.

Son zamanlarda deneyimlendiğim bir şey, bu nesneleri temsil eden satırları tablo halinde yapmak için yaptığım güncellemeleri en aza indirmeye çalışmak ve olabildiğince fazla eklemeler yapmaya çalışmak fikri.

Son zamanlarda deneyimlediğim bir şeyin somut bir örneği. Daha sonra ek veriler içeren bir kayıt ekleyebileceğimi biliyorsam, aşağıdaki iki tablo tanımını beğenmek üzere, bunu temsil etmek için başka bir tablo oluşturacağım:

create table myObj (id integer, ...other_data... not null);
create table myObjSuppliment (id integer, myObjId integer, ...more_data... not null);

Umarım bu isimler sözlü değildir, ancak sadece fikri göstermek için açıktır.

Bu veri kalıcılık modellemesinde makul bir yaklaşım mıdır? Bir tabloda gerçekleştirilen güncellemeleri, özellikle de kayıt oluşturulduğunda var olamayacak olan verilerin boş değerlerini doldurmakla sınırlamaya çalışmakta fayda var mı? Böyle bir yaklaşımın daha sonra şiddetli ağrıya neden olabileceği zamanlar var mı?


7
Bunun problemsiz bir çözüm olduğunu hissediyorum ... Güncellemekten kaçınmak için ayrıntılı uyarlamalar oluşturmak yerine güncellemelisiniz.
Fosco

Sanırım, akılda kalıcı bir çözüm fikri hakkında sezgisel bir fikre sahip olmak ve bunu mümkün olduğunca çok insan tarafından yürütmek istemekle ve bu sorunun benim için en iyi çözüm olmayabilir olabileceğini düşünüyorum. Başka yerde bulamazsam, sorunla farklı bir soru açabilirim.
Ed Carrel,

1
Veritabanlarında güncellemeleri önlemek için iyi nedenler olabilir. Ancak, bu nedenler ortaya çıktığında, bu daha çok bir optimizasyon problemidir ve bir problem olduğuna dair kanıt olmadan yapılmamalıdır.
dietbuddha

6
Veritabanlarında değişmezlik için güçlü bir argüman olduğunu düşünüyorum. Bir çok problemi çözer. Bence olumsuz yorumlar açık fikirli insanlardan gelmedi. Yerinde yapılan güncellemeler birçok sorunun nedenidir. Hepsini geri aldığımızı iddia ediyorum. Yerinde güncellemeler, artık var olmayan bir sorunun eski çözümü. Depolama ucuz. Neden yaptın? Kaç tane DB sisteminin denetim günlükleri, versiyonlama sistemleri, hepimizin bildiği gibi ölçeklendirme için gecikmeyi destekleme yeteneği gerektiren dağıtılmış çoğaltma ihtiyacı vardır. Taklit edilebilirlik tüm bunları çözer.
cirrus,

@Fosco Bazı sistemler kesinlikle veri silmek için zorunludur (kullanım dahil UPDATE). Doktorun tıbbi kayıtları gibi.
Izkata

Yanıtlar:


25

Değişmezliğin temel amacı, bellekteki veriler geçersiz bir durumda olduğunda zamanın anında olmamasını sağlamaktır. (Diğeri, matematiksel gösterimlerin çoğunlukla statik olması ve dolayısıyla değişmez şeylerin matematiksel olarak kavramsallaştırılması ve modellenmesidir.) Belleğe bakılırsa, başka bir işçinin çalıştığı sırada veri okumaya veya yazmaya çalıştığında, bozulmaya başlayabilir veya kendisi bozuk bir durumda olabilir. Bir nesnenin alanlarına birden fazla atama işleminiz varsa, çok iş parçacıklı bir uygulamada, başka bir iş parçacığı onunla arada çalışmayı deneyebilir - ki bu kötü olabilir.

Taklit edilebilirlik bunu, tüm değişiklikleri ilk önce bellekteki yeni bir yere yazarak ve ardından son ödevi tek bir basma basamağı olarak yaparak, işaretçiyi nesneye yeni nesneyi gösterecek şekilde yeniden yazma basamağı olarak yapıyor - tüm CPU'larda bir atom olan operasyon.

Veritabanları atomik işlemleri kullanarak aynı şeyi yapar : bir işlem başlattığınızda, tüm yeni güncellemeleri diskteki yeni bir yere yazar. İşlemi tamamladığınızda, diskteki işaretçiyi yeni güncellemelerin olduğu yere değiştirir - bu, kısa sürede anında diğer işlemlerin dokunamayacağı bir zamanda yapılır.

Bu, aynı zamanda daha otomatik ve daha esnek hariç, yeni tablolar oluşturma fikrinizle aynı şeydir.

Dolayısıyla sorunuzu cevaplamak için, evet, değişkenlik veritabanlarında iyidir, ama hayır, yalnızca bu amaç için ayrı tablolar oluşturmanıza gerek yoktur; veritabanı sisteminiz için ne tür bir atomik işlem komutunu kullanabilirsiniz.


Cevap için teşekkürler. Bu bakış açısı, sezgimin kafa karıştırıcı bir şekilde birkaç farklı fikri tek bir kalıpta birleştirmeye çalıştığını fark etmem için gerekli olan şeydi.
Ed Carrel

8
Dolandırıcılıktan biraz daha fazlası var. Bir OOP bağlamında değişmezlik lehine en sık gördüğüm argüman, değişmez nesnelerin yapıcıdaki durumlarını yalnızca bir kez doğrulamanızı gerektirdiğidir. Değişebilirlerse, durumlarını değiştirebilecek her yöntem, aynı zamanda, durumun hala geçerli olduğunu doğrulamak için zorunludur, bu da sınıfa önemli bir karmaşıklık katabilir. Bu argüman potansiyel olarak veritabanları için de geçerlidir, ancak db doğrulama kuralları prosedürden ziyade bildirimsel olma eğilimindedir, bu nedenle her sorgu için çoğaltılmaları gerekmez.
Dave Sherohman

24

Değişmezlikten elde etmeyi umduğunuz yararlara bağlıdır. Rei Miyasaka'nın cevabı bire hitap etti (geçersiz orta devletlerden kaçınıldı), fakat işte bir başka.

Mutasyona bazen yıkıcı güncelleme denir : bir nesneyi değiştirdiğinizde eski durum kaybolur (bir şekilde açıkça korumak için ek adımlar atmazsanız). Buna karşılık, değişken verilerle, bazı işlemlerden önce ve sonra aynı anda devleti temsil etmek veya birden fazla halefi durumu temsil etmek önemsizdir. Tek bir durum nesnesini mutasyona sokarak genişlik ilk aramayı uygulamaya çalıştığınızı hayal edin.

Bu muhtemelen veritabanı dünyasında en sık geçici veri olarak ortaya çıkmaktadır . Geçen ay, Temel planda bulunduğunuzu söyleyin, ancak 16'sında Premium plana geçtiniz. Hangi plan üzerinde olduğunuzu gösteren bir alanın üzerine yeni yazarsak, faturalandırmada haklı olmakta zorluk çekebiliriz. Ayrıca trendleri analiz etme yeteneğini de kaçırabiliriz. (Bu yerel reklam kampanyasının ne yaptığını görün!)

Zaten "veritabanı tasarımında değişmezlik" derken aklıma bu geliyor.


2
Üçüncü paragrafına katılmıyorum. Bir geçmişe sahip olmak istiyorsanız (denetim günlüğü, plan değişikliklerinin günlüğü vb.), Bunun için ayrı bir tablo oluşturmanız gerekir. CustomerKullanıcının planını değiştirdiğini hatırlamak için tüm 50 tablo alanını çoğaltmak , büyük performans dezavantajı dışında hiçbir şey getirmez, zaman içinde daha yavaş seçim yapar, daha karmaşık veri madenciliği (günlüklere kıyasla) ve daha fazla boşa harcanır.
Arseni Mourzenko

6
@MainMa: Belki de "bunun yerine geçici veritabanları hakkında okumaya devam et" demeliydim. Benim örneğim, zamansal verilerin ne olduğuna dair bir taslak olarak tasarlanmıştı; Değişen verileri temsil etmenin daima en iyi yolu olduğunu iddia etmiyorum. Öte yandan, geçici verilere yönelik destek şu anda oldukça zayıf olsa da, trendin değişim günlükleri gibi "ikinci sınıf" gösterimlerine aktarılmasından ziyade, geçici verinin veritabanının kendisinde yer almasını bekliyorum.
Ryan Culpepper

Bir denetim tablosunda değişiklik geçmişi tutarsak (örneğin bu özellik nedeniyle ilkbahar ve kış uykusu)?
Mohammad Najar

14

Veritabanındaki değişmezlikten veya en azından değişmezlik yanılsamasını sunan bir veri tabanından elde edebileceğiniz faydalarla ilgileniyorsanız, Datomic'i kontrol edin.

Datomic , Rich Hickey tarafından Think Alaevent ile bağlantılı olarak icat edilmiş bir Veri Tabanıdır , mimariyi, hedeflerini, veri modelini açıkladıkları birçok video vardır. Arama infoq, özellikle biri Datomic, Veritabanını Değer olarak adlandırır . Çatışmalarda, Rich Hickey’in 2012’deki euroclojure konferansında verdiği bir açılış konuşmasını bulabilirsiniz. Confreaks.com/videos/2077-euroclojure2012-day-2-keynote-the-datomic-architecture-and-data-model

Vimeo.com/53162418 adresinde daha fazla gelişim odaklı bir konuşma var.

İşte stuart halloway'dan başka bir sayfa daha :.pscdn.net/008/00102/videoplatform/kv/121105techconf_close.html

  • Datomic, 5-tuples [da, A, V, T, O] datums denilen zaman içindeki gerçeklerin bir veritabanıdır.
    • E Varlık kimliği
    • Varlıktaki bir Öznitelik adı
    • V Özelliğin Değeri
    • T İşlem Kimliği ile bunun için zaman fikriniz var.
    • O Bir iddia işlemi (şimdiki veya mevcut değer), reddetme (geçmiş değer);
  • EDN (Genişletilebilir Veri Notasyonu) adı verilen kendi veri formatını kullanır
  • İşlemler ACID
  • Datalog'yu sorgu dili olarak kullanır, hangi SQL + özyinelemeli sorgular olarak bildirilir. Sorgular veri yapılarıyla temsil edilir ve jvm dilinizle birlikte genişletin, clojure kullanmanıza gerek yoktur.
  • Veri tabanı 3 ayrı hizmette (süreçler, makineler) ayrıştırılır:
    • işlem
    • Depolama
    • Sorgu Motoru.
  • Her bir hizmeti ayrı ayrı ölçeklendirebilirsiniz.
  • Açık kaynak değil, fakat Datomic'in ücretsiz (biradaki gibi) sürümü var.
  • Esnek bir şema belirtebilirsiniz.
    • öznitelik kümesi açık
    • istediğiniz zaman yeni özellikler ekleyin
    • tanım veya sorguda sağlamlık yok

Şimdi, bilgi zaman içinde gerçekler olarak saklandığından:

  • tek yaptığınız veri tabanına gerçekleri eklemek, onları asla silmezsiniz (yasalarca gerekli olmadıkça
  • sonsuza dek her şeyi önbelleğe alabilirsiniz. Query Engine, uygulama sunucusunda bir bellek veri tabanı olarak yaşar (jvm dilleri için jvm dışındaki dillerin bir REST API'sine erişimi vardır.)
  • Geçmişte zaman olarak sorgulayabilirsiniz.

Veri tabanı bir değerdir ve sorgu motorunun bir parametresi olan QE, bağlantıyı ve önbelleği yönetir. Db'yi bellekte bir değer olarak ve değişmez veri yapısını görebildiğiniz için, onu "gelecekteki" değerlerden yapılan başka bir veri yapısıyla birleştirebilir ve bunu asıl veritabanını değiştirmeden QE'ye ve gelecekteki değerlerle sorgulamaya aktarabilirsiniz. .

Kodq olarak adlandırılan Rich Hickey'den açık kaynaklı bir proje var, onu git modelini genişleten ve git nesnelerine referansları veri içermeyen bir veritabanında saklayan ve kodunuzun sorgularını yapan github Datomic / codeq içinde bulabilirsiniz. datomic kullanımı hakkında bir örnek görebilirsiniz .

Veriyi bir ACID NoSQL olarak düşünebilirsiniz; verilerle tabloları veya belgeleri veya Kv-mağazalarını veya grafiklerini modelleyebilirsiniz.


7

Güncellemelerden kaçınma ve ekleri tercih etme fikri, veri depolamanızı bir Etkinlik Kaynağı olarak inşa etmenin arkasındaki düşüncelerden biridir, genellikle CQRS ile birlikte kullanacağınız bir fikirdir. Bir olay kaynağı modelinde güncelleme yoktur: bir toplama, "dönüşümünün" (olaylar) dizisi olarak temsil edilir ve sonuç olarak depolama yalnızca eklenir.
Bu site , eğer merak ediyorsanız, CQRS ve etkinlik kaynağı hakkında ilginç tartışmalar içeriyor!


CQRS ve Etkinlik kaynağı bu günlerde öne çıkmaktadır.
Gulshan

6

Bu, veri depolama dünyasında "Yavaşça Değişen Boyutlar" ve diğer alanlardaki "Temporal" veya "Bi-Temporal" tablolar olarak bilinenlerle çok yakın bir ilişki içindedir.

Temel yapı şudur:

  1. Her zaman birincil anahtar olarak oluşturulan bir yedek anahtar kullanın.
  2. Tanımladığınız şeyin benzersiz tanımlayıcısı "mantıksal anahtar" olur.
  3. Her satırda en az bir "ValidFrom" zaman damgası ve isteğe bağlı olarak "ValidTo" zaman damgası ve daha da isteğe bağlı olarak "En Son Sürüm" bayrağı bulunmalıdır.
  4. Mantıksal bir varlığın "oluşturulmasında", geçerli zaman damgasının "Geçerli Kimden" olan yeni bir satır ekleyin. İsteğe bağlı ValidTo "sonsuza kadar" (9999-12-31 23:59:59) ve Son Sürüm'ü "Gerçek" olarak ayarladı.
  5. Mantıksal varlığın daha sonraki bir güncellemesinde. En azından yukarıdaki gibi yeni bir satır ekleyin. Ayrıca ValidTo'yu önceki sürümdeki "now () - 1 second" ve En Son Sürüm "False" olarak ayarlamanız da gerekebilir.
    1. Mantıksal silme işleminde (bu yalnızca ValidTo zaman damgası ile çalışır!) Geçerli satırdaki ValidTo bayrağını "now () -1 second" olarak ayarlarsınız.

Bu planın avantajları, mantıksal varlığınızın "durumunu" herhangi bir zamanda yeniden oluşturabilmeniz, zaman içinde varlığınızın bir geçmişine sahip olmanız ve "mantıksal varlığınızın" yoğun olarak kullanılması durumunda çekişmeyi en aza indirmenizdir.

Dezavantajları, çok daha fazla veri saklamanızdır ve daha fazla dizin tutmanız gerekir (en azından Mantıksal Anahtar + ValidFrom + ValidTo'da). Mantıksal Anahtar + Son Sürümdeki bir dizin çoğu sorguyu büyük ölçüde hızlandırır. Ayrıca SQL'inizi de karmaşık hale getirir!

Bir tarihi korumanız ve varlıklarınızın durumunu belirli bir zamanda yeniden yaratmanız gerekmiyorsa, bunun yapmaya değip değmeyeceği size kalmış.


1

Değişmez bir veritabanına sahip olmanın bir diğer olası nedeni, daha iyi paralel işlemeyi desteklemek olacaktır. Sıra dışı gerçekleşen güncellemeler verileri kalıcı olarak karıştırabilir, bu nedenle paralel performansı yok etmek için kilitleme yapılması gerekir. Çok sayıda olay eki herhangi bir sırayla gidebilir ve tüm olaylar sonunda işlendiği sürece devlet en azından sonunda doğru olacaktır . Ben am - Ancak bu gerçekten şeyler bu şekilde mütalaa edecek paralellik çok ihtiyacımız zorunda kalacağını veritabanı güncellemelerini yapıyor kıyasla pratikte bu kadar zor iş olduğunu değil bunu tavsiye.


0

Yasal Uyarı: Ben DB: p hemen hemen bir yeniyim

Söylendiği gibi, bu veri satellizing yaklaşımı performans üzerinde hemen bir etkiye sahiptir:

  • İyi birincil masaya daha az trafik
  • Birincil tabloda iyi küçük satırlar
  • Uydu verilerini gerektiren kötü , başka bir aranmanın gerekli olduğu anlamına gelir
  • Kötü tüm nesnelerin her iki tabloda varsa daha fazla yer işgal

Gereksinimlerinize bağlı olarak, bunu memnuniyetle kabul edebilir ya da kabul etmeyebilirsiniz, ancak bu kesinlikle göz önünde bulundurmanız gereken bir husustur.


-1

Planınıza nasıl "değişmez" denebileceğini anlamıyorum.

Ek tabloda depolanan bir değer değiştiğinde ne olur? Bu masada bir güncelleme yapmanız gerekecek gibi görünüyor.

Bir veritabanının gerçekten değişmez olması için, yalnızca "INSERTS" ile korunması gerekir. Bunun için "current" satırını tanımlamak için bazı yöntemlere ihtiyacınız var. Bu neredeyse her zaman korkunç derecede yetersiz kalıyor. Daha önce değişmemiş tüm değerleri kopyalamanız ya da sorguladığınızda mevcut durumu birkaç kayıttan bir araya getirmeniz gerekir. Geçerli satırın seçimi genellikle ( where updTime = (SELECT max(updTime) from myTab where id = ?) gibi bazı korkunç dağınık SQL gerektirir .

Bu sorun DataWarehousing'de, zaman içinde verilerin geçmişini tutmanız ve zaman içindeki herhangi bir nokta için durumu seçebilmeniz gereken yerlerde ortaya çıkar. Çözüm genellikle "boyutsal" tablolardır. Ancak, DW'yi "geçen Ocak ayında satış temsilcisi kim" sorunu çözerken. Javas değişmez sınıflarının sağladığı hiçbir avantajı sağlamazlar.

Daha felsefi bir kayda göre; "durum" (banka bakiyesi, elektrik tüketiminiz, StackOverflow'ta brownie puanları vb.) depolamak için veritabanları var, "vatansız" bir veritabanı bulmaya çalışmak oldukça anlamsız bir uygulama gibi görünüyor.


Tek bir kayıt için, WHERE id = {} ORDER BY updTime DESC LIMIT 1genellikle çok verimsiz değildir.
Izkata

@Izkata - :-) katılmak üç masanın hte ortasında koymayı deneyin
James Anderson
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.