Profesör ilişkisel tabloları tanımlamak yerine serileştirilmiş Java nesnelerini blob olarak saklamamızı söyledi.


21

Aslında doğru özniteliklere sahip bir tablo tanımlamak yerine profesör, nesneleri şöyle tanımlayabiliriz:

id (int)  |   Serialized Object (blob)
   1               10010110110

Bununla ilgili birçok problem görebiliyorum; veri fazlalığı, kimlikleri ayrı ayrı izlemek zorunda, tüm tabloyu bir şey aramak için belleğe çekmek zorunda kalıyor ve ** modelimi Java kodunda değiştirmek istersem, artık depoda depolanan bloğu seri hale getiremeyeceğim Bu modelin içine veritabanı.

Ya sonsuza dek o modelle takılıyorum ya da modelimi değiştirmek için gerçekten çirkin şeyler yapmak zorundayım. ** Bu şeyler bana kötü geliyor. Profesörüme katılmamakta haklı mıyım? Bunu düşünmediğim için bir faydası var mı? Eğer haklıysam, profesörüme bu konuda bir şey mi söylemeliyim? Bunu bütün sınıfıma yayıyordu ve hatta bu şekilde projeler yaptığını söyledi. İkinci bir fikir çok iyi olurdu.

Tabii Yazılım Tasarımı .

Profesörüm bunun en iyi yol olduğunu söylemedi, ancak ilişkisel tabloları tanımlamanın meşru bir alternatifi olduğunu söyledi.

Model hiçbir şekilde dinamik değil.


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Paul White GoFundMonica

Yanıtlar:


34
  1. Bu, kendi başına, kötü bir şey değil - hiç. Uygun bir bağlam olmadan (= kesin şartlar) “hangisinin daha iyi olduğunu” tartışmak boşuna bir alıştırmadır.

  2. Kalın yazılmış kısım yanlış. Yeni alanlar eklemek ve eski nesnelerle tam ikili uyumluluk elde etmek için halihazırda seri hale getirilmiş nesneleri kolayca genişletebilirsiniz. Orijinalleri değiştirmek yerine, sadece yeni sınıflar oluşturabilirsiniz.

Profesörle yaptığınız görüşmeniz, farklı "senaryolara göre" ilişkisel "ve" anahtar-değer deposu "nun artılarına ve eksilerine odaklanmalıdır. Ya da Noel'in Şükran Günü'nden üstün olup olmadığı hakkında da bir tartışma yapabilirsiniz.

- diğer cevapları okuduktan sonra bir düzenleme.

Diğer cevaplardan biri, "artıların eksilere ağır bastığı bir durumu hayal etmenin zor olduğunu" söylemeye kadar gider.

Tüm tartışmanın somut problemlerle ilgili olması gerektiğinden (aksi takdirde "daha iyi" ve "daha kötüsünü" bile tanımlayamıyoruz), size bir somut örnek vereyim. Tamamen uydurdum, ama mümkün olduğunca fazla ayrıntıyı ortaya çıkarmaya çalıştım.

Bir çevrimiçi oyun siteniz olduğunu, farklı çevrimiçi oyunlarda oyuncuların istatistiklerini saklayan bir veritabanına sahip olduğunu (tarayıcıda oynanmış, GWT ile yazılmış ve javascript'e çapraz derlenmiş) düşünün. Oyunların bazıları stratejik, bazıları aksiyon oyunları, bazıları platformist. Veri tabanı ilişkiseldir ve oyuncuları, oyunların tarihçesini ve puanları depolar.

Bir gün ek bir gereksinim alırsınız: Oyuncuların oyun sırasındaki oyun durumunu buluta kaydetmelerine izin verin, böylece oyunu daha sonra yeniden başlatabilirler. Söylemeye gerek yok, bu geçici durumu saklamak için tek neden oyuna geri dönmek, devletin kendisi hiçbir zaman iç içe geçmeyecek.

Şimdi iki temel seçeneğiniz var:

  • Oyunlar Java ile yazılmış olduğundan, modeli kolayca alabilir, sunucuya gönderebilir, tek bir kod satırında serileştirebilir ve blob olarak saklayabilirsiniz. Masa "saved_games" olarak adlandırılır ve oyuncuya vb. Yabancı anahtarlar konur. Veri tabanı açısından bir "oyun kaydet", opak, bölünemez bir blobdur.

  • 100 oyununuzun her biri için ayrı bir ilişkisel model oluşturabilirsiniz (bu, oyun başına onlarca masa olacaktır). Sadece pacman için, örneğin, tüm yenilmemiş peletlerin, bonusların, pozisyonların ve mevcut hayaletlerin durumlarını depolayan bir masaya sahip olmanız gerekir. Birisi, bir gün, oyunu biraz değiştirse bile, ilişkisel modeli güncellemeniz gerekecektir. Ayrıca, her oyun türü için, Java modelini veritabanına yazmak ve onu okumak için bir mantık uygulamanız gerekecektir.

Justin Cave'nin cevabı, ikinci seçeneğe gitmeniz gerektiğini söylüyor. Bunun çok büyük bir hata olacağını düşünüyorum.

Ayrıca, Justin Cave’in algısının yukarıda sunduğumun "kenar" ya da "nadir" bir durum olduğu konusunda bir fikrim var. Bir tür zor veri sunamadığı sürece (sadece ABD'deki kurumsal uygulamaların değil, dünyadaki tüm BT projelerinin temsili bir örneklemesine dayanarak), böyle bir fikrin bir projeksiyon olayı olarak göreceğime inanıyorum. önyargı.

Aslında ilişkisel bir veritabanında serileştirilmiş Java nesnelerinin sorunu göründüğünden çok daha derin. 1NF'nin özüne dokunuyor, yani bir özniteliğin alanı nedir? . Konuyla gerçekten ilgileniyorsanız, CJ Date'in Veritabanında Yazdığı Tarih: 2000-2006 adlı harika bir makale var .


Yorumlar uzun tartışmalar için değildir; bu konuşma sohbete taşındı .
Paul White GoFundMonica

22

İnsanlar bu tür şeyleri yapan projeleri başarılı bir şekilde sunabilir mi? Ne yazık ki, evet, bunu oldukça sık sık yaparlar.

Bu iyi bir yaklaşım mı? Hayır değil. Temelde nispeten pahalı veritabanınızı alıyor ve onu nispeten yavaş bir dosya sistemine dönüştürüyorsunuz. Nesneleri seri hale getirerek ve serileştirerek durumunu kaydeden bir sistem oluşturmak istiyorsanız, veritabanı kullanmak yerine bir dosya sistemi de kullanabilirsiniz.

Nesneleri veritabanına seri hale getirerek veri depolayan sistemler kurarsanız, DBA'nızla arkadaş olamazsınız. Gereksiz verileri saklamanız gerekir. Sonunda tutarsız verilerle sonuçlanırsınız; paylaşılan veriler her güncellendiğinde, bazı nesneler yeni değerlerle sonuçlanır ve bazı nesneler eski değerlerle sonuçlanır. Veriler hakkında herhangi bir raporlama yapmayı imkansız hale getireceksiniz - verilerle yapmak isteyen herkesin ek kod yazmasını gerektirecek. Bu, çoğu işletmede çok büyük, çok büyük bir sorun çünkü bir sistemden veriyi başka bir sisteme yüklemek üzere veri ayıklamak veya birden fazla ön uç uygulamasından raporlar alabilen bir raporlama sistemine sahip olmak istiyorlar. Artı, sizin de belirttiğiniz gibi, sürekli sorunlarla baş etmek zorunda kalacaksınız.

Bu yaklaşımın avantajları var mı? Sanırım uygulamanın ilk sürümünü uygulamak oldukça kolay. Ve geliştiricinin bir veritabanıyla düzgün şekilde etkileşime girme ile ilgili herhangi bir şeyi tamamen görmezden gelmesini sağlar. Bu avantajların yaklaşıma olan sayısız olumsuzluktan ağır bastığını gösteren birçok durumu hayal etmeye zorlanıyorum.

Bu özel profesörle nasıl başa çıkmanız gerektiğine gelince, bu ayrı bir konu (ve muhtemelen bu forumun kapsamı dışında olan). Profesörünüz aktif olarak gerçek dünyada projeler geliştiriyorsa, muhtemelen bir öğrencinin yaklaşımının temelde yanlış olduğu (herhangi bir temelde yanlış olsa bile) bir argümana korkunç derecede açık davranmayacaktır. Projenizi profesörün istediği şekilde yapmak ve kendi başınıza (veya farklı bir kursta) veri kaydetmek için doğru yolu öğrenmek size daha iyi hizmet verebilir.


2
Ne dedin, artı iki kuruş. Yeniden kullanılabilirlik modülerlik ve paylaşımla ilgilidir. Nesne modeli, nesneleri paylaşmaya ve kodu yeniden kullanmaya odaklanır. Veri tabanı modeli verileri paylaşmaya ve tekrar kullanmaya odaklanır. Her iki model de tamamen moronik değildir. Her iki model de mükemmellik değil. Ve ikisini uzlaştırmak çok ama çok zor.
Walter Mitty

1
Buna katılıyorum, ancak bir profesörün bir şey öğrettiğini görmekten nefret ediyorum ve bununla yüzleşmeden daha iyi bir yol olduğunu söylüyorum. Peki ya diğer fakir öğrencilere, bunun doğru yol olduğunu düşünerek gerçek dünyaya girecek olan sınıf?
Kevin

Emin. Bu formülasyon, veri gibi davranan objeleri tutar. Ve onlar veridir, fakat çok faydalı veri değildir.
Walter Mitty

Avantajınız, uygulamanızın v2'sini serbest bırakmak istediğinizde neredeyse her zaman silinir.
Andy

10

Bu tür bir tasarımın mantıklı olduğu durumlar vardır, projelerinizin neyle ilgili olduğunu ve nasıl kullanıldığını açıklamadan, bunun uygun olup olmadığını söylemek zordur.

BLOB'ları saklarsanız DBA'nız sizden nefret edebilir, ancak çoğu durumda tek alternatif, tabloları DBA'lardan daha fazla nefret alan varlık-özellik değerine dönüştürmektir. Diğer bir alternatif ise ilişkisel olmayan veritabanları, genellikle nesne tabanlı veya sözlük tabanlı veritabanları veya bazı DBA'ların, özellikle sadece ilişkisel bilenlerin daha fazla tutkuyla nefret edeceği belgeye dayalı bir veritabanı kullanmaktır. İlişkisel olmayan veritabanının ele alınması gereken kendi sorunları vardır, ancak nesneleri saklamak için nesne veritabanını kullanmanın, ilişkisel sistemlerde kolayca çözebileceğiniz diğer sorunları ortaya çıkarması söz konusu olabilir.

Bunu düşünmediğim için bir faydası var mı?

Serileştirilmiş nesneyi saklamak, şemasız verileri depolayabileceğiniz anlamına gelir (ismine rağmen, şemanın genellikle hiçbir şema olmadığı anlamına gelmediğini, ancak yalnızca örtülü şemalar bulunduğunu unutmayın). Geliştirme zamanında vaktinden önce şema tanımlayamadığınız ve geleneksel ilişkisel veritabanı tasarımını izlemenin, her hafta veri tabanının şemasını değiştirmek zorunda kalacağınız veya bir tabloya sahip olacağınız anlamına gelen birçok sorun alanı vardır. Zamanın% 80'i kullanılmayan sütunların% 80'i veya hiçbiri iyi bir tasarım olmadığını gösteren aynı veriyi saklamak için yüzlerce farklı tablo. Bu sorunun kökü, genellikle ilişkisel olmayan bir problem alanını ilişkisel bir veritabanına yerleştirmeye zorlamanızdır.

Tabii ki, insanların gereksiz yere kaçınılması gereken bir acıya neden olacak sonuçta EAV, şema ya da damla deposu kullanmaları gerektiğini düşündüğü birçok proje var. Profesörünüze kesinlikle mantığının ne olduğunu tartışmalı ve kendi argümanlarınızı sağlamalısınız; Argümanları dinleyin ve onunla aynı fikirde olabilirsiniz, belki de yanılıyor olabilirsiniz.


7

Bunu daha önce yaptım - onun belirli senaryolarda faydalı bir tekniği ancak kullanılan seri hale getirme formatına bağlı. Bunu yaparsam, modelimin eski sürümlerini (örn. XML) seri hale getirmeme izin veren bir serileştirme biçimi kullandığımdan emin olun.

Normalde bunu, veri formatının avantaj sağlamayan karmaşık bir ilişkisel modelle sonuçlanacağı senaryolarda kullanırdım (örneğin, işletme gereksinimleri herhangi bir filtreleme gerektirmediğinde…) ve ben zaten bir veritabanı kullanıyorum diğer ilişkisel veriler). Böyle bir durum, kullanıcı sorguları olan bir uygulamadır - ilişkisel modelde koşullar, iç içe koşullar (VE / VEYA vb.), Sıralama seçeneklerini vb. Gibi şeyleri depolamak için bir avuç tablo vardı. Veritabanında değişiklik gerektiren yeni bir özellik eklemeye ihtiyacımız vardı. Her şeyi, diğer tüm seçenekleri temsil eden serileştirilmiş bir blob ile tek bir sorgu tablosuyla değiştirdim.

Diğer bir durum, çeşitli "işleri" işleyen bir sistemdi. Birkaç farklı iş türü vardı ve her işin farklı parametreleri vardı, bu parametreleri temel alan işleri arayabilen / filtreleyebilen hiçbir iş gereksinimi yoktu. Bunu ilişkisel bir veritabanı olarak saklamak, iş türü başına en az 1 yeni tablo gerektiriyordu ve bu da yeni iş türleri eklemeyi zorlaştırıyordu. Bunun yerine, parametreler veritabanında bir blob olarak depolanır - her iş türü kendi parametrelerinin serileştirilmesi ve serileştirilmesinden sorumludur.

Çok sık değil, böyle senaryolarla karşılaşacaksınız, ancak her gün ve sonra blob verilerinin serileştirilmesinin sizi çok fazla çaba harcadığı, uygulamanızı daha sürdürülebilir hale getirdiği ve hiçbir dezavantajı bulunmadığı durumlarda ortaya çıkan bir durum ortaya çıkıyor.


6

Justin Cave, bunun gereksiz veriye yol açabileceği konusunda doğrudur, ancak bu gerçekten veritabanınızı nasıl tasarladığınıza bağlıdır.

Bütün bir nesneyi bir blob içine serileştirme yaklaşımı, buradaki çoğu insanın düşündüğü kadar çirkin değildir. Aslında, bazı uygulamalar için, burada açıkladığım gibi, yapabileceğiniz en iyi tasarım olabilir: /programming//a/12644223/1121352 .

Aslında, bir nesneyi seri hale getirmek en az iki fayda sağlar:

1- Impedence uyumsuzluğunu azaltmak : Bazı Java tipleri SQL'de mevcut değildir, özellikle de çok sayıda sınıf ve özel tip kullanıyorsanız, Java nesnelerinden SQL'e ileri geri dönüştürme büyük bir güçlük olabilir ve hatta belirsizliklere yol açabilir.

2- Şemanızda daha fazla esneklik . Aslında, ilişkisel şemalar aynı yapıyı paylaşan veriler için gerçekten harikadır, ancak tek bir sınıftaki nesnelerinizden bazıları çalışma zamanındaki koşullara bağlı olarak farklı özelliklere sahipse, ilişkisel şemalar iş akışınızı önemli ölçüde engelleyebilir.

Bu nedenle, kesinlikle bu yaklaşımın faydaları vardır (en azından bu ikisi, ama kesinlikle bahsetmediğim diğerleri), ama elbette, ödenmesi gereken büyük maliyet, neredeyse tüm ilişkisel şemaların yararlarını kaybetmenizdir.

Bununla birlikte, veritabanınızı dikkatlice tasarlarsanız her iki dünyanın en iyisini elde edebilirsiniz: yine de her nesne için benzersiz olan öznitelikleri kullanarak bir ilişki şeması (yani benzersiz anahtar sütunlar) ayarlayabilir ve ardından nesneyi blob içinde saklayabilirsiniz. . Bu şekilde, nesnenin özniteliklerine göre tanımlanmış benzersiz bir tanımlayıcı verildiğinde nesnenin hızlı bir şekilde alınmasını sağlayabilirsiniz, ayrıca fazlalık oranını azaltıp, çarpışma uyumsuzluğunu yok edip Java nesnelerinin tam esnekliğini koruyabilirsiniz.

Yan not olarak, bazı DB üreticileri tarafından ilişkisel ve nesne modellerini birlikte harmanlama denemeleri, PostSQL ve PostgreSQL'deki JSON veri türü gibi, böylece JSON'yu doğrudan herhangi bir ilişkisel sütun gibi işleyebilmeniz ve SQL3 ve OQL (Nesne Sorgu Dili) eklemek (sınırlı) nesneleri SQL içine destekler.

Sonunda, tüm bunlar ilişkisel model ile nesne modeli arasında bir tasarım ve uzlaşma sorunudur.

/ Yorumları okuduktan sonra EDIT : tabii ki, eğer verileriniz aranabilir ise ("sorgulanabilir"), verilerinizi blob olarak saklamamalısınız. Ancak verilerinizin bazı bölümlerinin aranabilir olması yerine, bir tür meta-veri olması gerekiyorsa, bu veri bölümünü bir blob içindeki bir nesne olarak saklamak, özellikle de bu meta-veri esnek bir yapıya sahipse, iyi bir çözüm olabilir. ve nesneden nesneye değişebilir.


5

Bunu geçmişte ne zaman yaptığımın pratik bir örneğini verelim.

Çok kullanıcılı bir uygulamanın tüm verilerini içeren bir veritabanımız var; Veritabanında ayrıca erişim haklarına sahip bir kullanıcı tablosu vardır. Bu verilerin tümü beklendiği gibi normalleştirilmiştir.

Ardından, uygulamanın bir kullanıcının hangi pencereleri açtığını ve ne yaptıklarını hatırlamasını istedik, böylece kullanıcı ertesi sabah çalışmaya başladığında durumu geri yükleyebilir.

  • Birincisi, bu bazen başarısız olursa, belirsiz değil mi?

    • Örneğin, ilk kez birisi uygulamanın yeni bir sürümünü kullanıyorsa, açtıkları pencereleri unutur, yani…
  • Bu nedenle, nesneler değişirse% 100 geri dönüş vardır ve bu yüzden bloğu okuyamıyoruz.

  • Zaten erişim kontrolü, yedekleme vb. İçeren merkezi bir veritabanımız var.
  • Verileri dosyalara kaydetmenin maliyeti yüksektir, çünkü dosyalar tüm kullanıcı makinelerinin erişebileceği bir tür dosya sunucusuna yerleştirilmeli veya bu dosyaları okumak için bir API yazılmalıdır.

Başka bir zaman , çok uzun süren hesaplama yapan bir uygulamamız vardı ve kullanıcılar bir elektrik kesintisi varsa, hesaplamaları en son bilinen iyi noktadan yeniden başlatabilmek istiyorlardı. uygulamaların hesaplamaları yeniden başlatması beklenebilir ve kaydedilmesi gereken çok sayıda nesne olduğu için verilerin normalleştirilmesi pahalı olurdu.

Veritabanının mevcut olması ve iyi tanımlanmış normalleştirilmiş uygulama verileri için kullanılmasından ve blogları saklamak için kullanılmamasının gerçek bir nedeni olmadığından, mantıklı ve hızlı bir seçenek seçtik.


4

Çok önemli bir faktör: Java serileştirmesi (uygulayarak gerçekleştirilmiş olan Serializable), kendi içinde çok kötü bir formattır, bu yüzden kalıcı nesne depolaması için gerçekten kullanmamalısınız.

Java serileştirmenin sakıncaları:

  • Veriler diğer dillerden gerçekten okunamıyor.
  • Serileştirilmiş nesnelerin ileriye dönük uyumluluğunu korumak çok kolay değildir, yani: sınıfa alan eklerseniz (veya kaldırırsanız) sınıfın önceki sürümünde oluşturulan nesneleri okumak o kadar kolay olmaz.
  • O kadar hızlı değil (ancak kilometreniz değişebilir)

Eğer başka bir seri hale getirme formatı kullanırsanız, güzel bir Anahtar Değer deposu elde edersiniz, eğer java seri hale getirmeyi kullanırsanız karışıklık elde edersiniz.


Cevaptaki gerçekler yanlıştır: 1) format ayrıntılı bir şartname ile kaplıdır; 2) alan eklemek hiç sorun değil, format çok esnek; 3) hız gerçek verilere bağlıdır, ancak JSON veya XML gibi formatlarla karşılaştırılabilir (bazen daha hızlı, bazen daha yavaş). Temel olarak, cevabın tamamı bir satır hariç, yanlıştır: "veri diğer dillerden gerçekten okunamaz".
fdreger 23:14

1
Bunun dışında 1)yanlış olan cevap IMO geçerlidir. Deserialisaton üzerinde kontrol sahibi olmak istiyorsanız - alanları eklerken / silerken (ve özellikle son alanlar varken) gerekli olan arayüzler hantal görünüyor ve gerekli olduğu readObjectve readReplace(son alanlar için) daha fazla yöntemi geçersiz kılmanız gerekiyor .
jb.

Hatalısınız, alan ekleyip kaldırmak herhangi bir yöntem gerektirmez. Nihai alanlara gelince - asıl cevabınız onlardan hiç bahsetmiyor ve eğer öyle olsaydı, ilgisiz olurdu (sorun diğer tüm formatlar için ortak olurdu). Son olarak, "O kadar hızlı değil (ama kilometreniz değişebilir)" diyerek hiçbir şey ifade etmiyor. Tek bir hakkın var: diğer diller hakkında. Bu bir şeyleri "karışıklık" olarak adlandırmak için çok zayıf bir temel.
fdreger 23:14

1
Alan eklemek, herhangi bir yöntem yazmanızı gerektirmez, ancak bunların nasıl seri hale getirildiğini etkilemek istiyorsanız, bu davranışı belirtmeniz gerekir. Gelişmekte olan nesne şemasının seri hale getirilmesiyle ilgili sorunlara bazı referanslar bulmaya çalışacağım.
jb.

3

Bu, bazı iyi düşünülmüş cevaplarla ilginç bir konu. Serileştirilmiş nesneleri saklama ve almanın tüm sonuçlarına muhalif olmamak, bir DBA ekibine veya geliştirme ekibine verebileceğim cevabı vermenin ilginç olacağını düşünüyorum:

Önemli olan mevcut ve gelecekteki gereklilikleri karşılamak ve çözümü, gelecekteki destek çalışmalarını en aza indirmek için mümkün olduğunca basit tutmaktır. Hem işlevsel gereksinimler hem de işlevsel olmayan gereksinimler (örneğin altyapı ve veritabanı) karşılanmalıdır. 80/20 kuralını hatırlayın. Uygulamanın işletmedeki önemini ve hangi kalkınma çabasının uygun olduğunu anlayın.

Sorun olmazsa veritabanı alanı, hızı ve hafızasına takılmayın.

Bir DBMS onaylı listenizdeyse, uygun maliyetler olduğu sürece bir çözümde kullanabilirsiniz. Basit Blob'ları saklamak için İlişkisel Veritabanını kullanmakta sorun yoktur, özellikle de bu işleri kolaylaştırıyorsa.

Çözüm bir prototip veya erken aşama / sürüm olacaksa, işleri basit tutmak için daha fazla stres uygulanır. Veri şemasını, planladığınız sürece istediğiniz zaman genişletebilirsiniz.

Şema kendine ait bir iş alanını kapsamıyor ve iş kuralları katı değilse, ilişkisel veritabanlarının bütünlüğü veya tutarlılığı zorlamadığını unutmayın. (örneğin Seri Nesne Sorusunun çözümü, kuralları uygulamak için bir sözlük / ontoloji stili deposunu düşünebilir).

Tüm ilişkisel veritabanlarının saf ilişkisel veritabanı şemaları (örneğin, yıldızlar, boşluk, ilişkisel olmayan ..) kullanmadığı düşünüldüğünde, uygulamalar ilişkisel veritabanlarını söz konusu olduğu gibi ilişkisel olmayan depolar olarak da kullanabilirler. Birçok çekirdek iş veritabanı bu şekilde çalışı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.