MongoDB ve PostgreSQL'in birlikte kullanılması


25

Mevcut projem esasen değirmen döküman yönetim sisteminin bir çalışması.

Bu, bazı kırışıklıklar olduğunu söyledi (sürpriz, sürpriz). Bazı kırışıklıklar projeye oldukça özel olsa da, kanonik bir cevabı olmayan (yine de bulabildiğim) ve daha geniş bir problem alanına uygulanabilir bazı genel gözlemler ve sorular olduğuna inanıyorum. . Burada çok şey var ve StackExchange Q&A formatına uygun olduğundan emin değilim ama bence a) cevaplanabilir bir soru ve b) topluluğa fayda sağlayacak kadar spesifik değil. Düşüncelerimden bazıları bana özgü, ancak sorunun hem SQL hem de NoSQL vs her ikisine de karar vermiş olan herkes için yararlı olabileceğini düşünüyorum.

Arkaplan:

Yaptığımız web uygulaması, doğada açıkça ilişkisel olan veriler ile belge yönelimli veriler içerir. Bizim pastamızı da yemek isteriz.

TL; DR: Sanırım aşağıda 5. numara koku testini geçiyor. Yapıyor musun? SQL ve NOSQL'in böyle bir entegrasyonla tek bir uygulamada deneyimi olan var mı? Aşağıda bu problem sınıfına olası tüm yaklaşımları listelemeye çalıştım. Gelecek vaat eden bir alternatifi kaçırdım mı?

karmaşıklıklar:

  • Birçok farklı belge sınıfı var. Bu gereksinimler zaten onlarca farklı belgeyi gerektiriyor. Bu numara sadece hiç artacak. Mümkün olan en iyi durum, etki alanı uzmanlarının DBA'ların veya programcıların müdahalesi olmadan yeni belge sınıflarının eklenmesiyle başa çıkabilmeleri için basit bir etki alanına özgü dil, kod oluşturma ve esnek bir şemadan yararlanabileceğimiz bir durum olabilir. (Not: Greenspun'un Onuncu Kuralı'nı yaşadığımızın farkında zaten )
  • Başarılı önceki yazıların bütünlüğü, projenin merkezi bir gereksinimidir. Veriler iş için kritik öneme sahip olacak. Yazmadaki tam ACID anlambilimi, başarılı bir şekilde yazılı olanların yazılı kalması şartıyla feda edilebilir.
  • Belgeler kendileri karmaşık. Özel durumumuzdaki prototip belgesi, belge örneği başına 150+ farklı veri parçasının depolanmasını gerektirecektir. Patolojik vaka, büyüklük sırası daha kötü olabilir, fakat kesinlikle iki değil.
  • Tek bir belge sınıfı, daha sonraki bir zamanda güncellemelere tabi olan hareketli bir hedeftir.
  • Django'dan aldığımız ücretsiz şeyleri ilişkisel bir veritabanına bağladığımız zaman seviyoruz. Django-nonrel çatalını kullanmak için iki Django versiyonunu geri atlamak zorunda kalmadan freebies'i korumak istiyoruz. ORM'nin tamamen boşaltılması, 1.3'e düşürülmek için tercih edilir.

Temel olarak, ilişkisel verilerin karmaşası (kullanıcılar, gruplar vb. Gibi tipik web uygulaması nesnelerinizin yanı sıra gerçek zamanlı olarak karmaşık sorgularla dilimleyip açabilmemiz gereken belge meta verileri) ve belge verileri (ör. katılmak veya sorgulamakla ilgilenmediğimiz yüzlerce alan - veriler için tek kullanım durumumuz, girildiği tek belgeyi göstermek için olacaktır).

Bir akıl sağlığı kontrolü yapmak istedim (gönderi geçmişimi kontrol ederseniz, DBA olmadığım gerçeği hakkında oldukça açık bir şekilde), tercih edilen yöntemimde diğerlerinin çözmesi için karşılaştığım seçeneklerin tümünü numaralandırdım. hem ilişkisel hem de ilişkisel olmayan verileri içeren benzer problemler.

Önerilen çözümler:

1. Belge sınıfı başına bir tablo

Her belge sınıfı, tüm meta veriler ve veriler için sütunlarla birlikte kendi tablosunu alır.

Avantajları:

  • Standart SQL veri modeli oyunda.
  • İlişkisel veriler mümkün olan en iyi şekilde ele alınır. Gerekirse daha sonra normalize edeceğiz.
  • Django'nun yerleşik yönetici arayüzü bu tablolara göz gezdirmek için rahattır ve ORM kutudan çıkan verileri% 100 ile mutlu bir şekilde yaşayabilir.

Dezavantajları:

  • Bakım kabusu. Düzinelerce (yüzlerce?) Tablonun (onlarca?) Binlerce sütunu vardır.
  • Hangi tabloya yazılacağına tam olarak karar vermekten sorumlu uygulama düzeyinde mantık. Tablo ismini bir sorgu için parametre yapmak.
  • Temel olarak tüm iş mantığı değişiklikleri, şema değişiklikleri gerektirecektir.
  • Patolojik durumlar, tekli formlar için birden fazla tablodaki şeritleme verilerini gerektirebilir (bkz: PostgreSQL tablosundaki maksimum sütun sayısı nedir? ).
  • Muhtemelen, yaşamdan ve bizden nefret edecek kadar şüphesiz, gerçek, dürüst bir Tanrı DBA'sı bulmamız gerekecek.

2. EAV modellemesi

Sadece bir alan tablosu var. Varlık-Nitelik Değer modellemesi zaten iyi anlaşılmıştır. Bütünlüğü sağlamak için dahil ettim. 2013'te başlatılan herhangi bir projenin bilerek EAV yaklaşımıyla sonuçlanacağını sanmıyorum.

Avantajları:

  • Modellemesi kolaydır.

Dezavantajları:

  • Sorgulaması daha zor.
  • DB katmanı, artık bir uygulama düzeyinde nesne oluşturan şey için doğrudan bir gösterime sahip değildir.
  • DB seviyesi kısıtlama kontrolünü kaybederiz.
  • Bir masadaki satır sayısı 100 ile 1000 kat daha hızlı büyüyecek. Muhtemelen gelecekteki acı noktası, performans açısından.
  • Sınırlı indeksleme mümkün.
  • DB şeması, ORM ile ilgili olarak saçmadır. Piller dahil web uygulaması öğeleri korunur, ancak özel veri modelleri özel sorgular gerektirecektir.

3. PostgreSQL hstore veya json alanlarını kullanın.

Bu alan türlerinden biri, ilişkisel bir DB bağlamında şema verilerini depolamak için hile yapar. Bu çözüme atlamayın tek nedeni hemen (8.4 sürümünde çok değil tanıtıldı nispeten yeni olduğu bu yeni), ben buna sıfır önceki poz var ve şüpheli. Tam da aynı şekilde beni yanlış olarak vurguluyor, tüm güzel, kolayca normalize edilmiş verilerimi Mongo'ya atmaktan rahatsız olduğumu hissetmiştim - Mongo belgeler arasında referansları kullanabilse bile.

Avantajları:

  • Django ORM ve yerleşik auth ve session yönetiminin avantajlarından yararlanırız.
  • Her şey, daha önce diğer projelerde başarıyla kullandığımız bir arka uçta kalır.

Dezavantajları:

  • Kişisel olarak, bu konuda deneyim yok.
  • Çok kullanılan bir özellik gibi görünmüyor. NOSQL çözümlerine bakan insanlara biraz tavsiye edildikleri anlaşılıyor ama seçildiklerine dair pek fazla kanıt göremiyorum. Bu bana bir şey kaçırmam gerektiğini düşündürüyor.
  • Depolanan tüm değerler dizgedir. DB seviyesi kısıtlama kontrolünü kaybet.
  • Hstore'daki veriler, bir belgeyi özellikle görüntülemedikleri sürece kullanıcıya gösterilmez, ancak daha standart sütunlarda depolanan meta veriler olacaktır. Bu meta veriyi yeneceğiz ve yaratacağımız büyük hstorların performansın dezavantajları olabileceğinden endişe ediyorum.

4. Tam delikli belge odaklı gidin

Her şeyi belgeler yapın (MongoDB anlamında). Tek bir tür koleksiyon oluşturun Documentve bir gün arayın. Tüm çevresel verileri (kullanıcı hesapları, gruplar vb. Dahil) mongo'ya getirin. Bu çözüm açıkça EAV modellemesinden daha iyidir, ancak aynı sebepten dolayı bana yanlış geliyor # 3 yanlış hissettirdi - ikisi de çekiçinizi tornavida olarak kullanmak gibi hissediyorlar.

Avantajları:

  • Önceden verileri modellemeye gerek yok. Bir tür belgeyle bir koleksiyona sahip olun Documentve bir gün arayın.
  • Bilinen iyi ölçeklendirme özellikleri, koleksiyonun milyonlarca, hatta milyarlarca belgeyi kapsayacak şekilde büyümesi gerekiyorsa.
  • JSON formatı (BSON) geliştiriciler için sezgiseldir.
  • Anladığım kadarıyla (sadece bu noktada belirsiz olan), yazma kaygısı seviyesine gelince paranoyak olmak, tek bir örnek bile bir şey ve bir sabit disk arızası durumunda her şeyde oldukça güçlü veri güvenliği sağlayabilir.

Dezavantajları:

  • ORM, Django trunku için camın dışında. Onunla birlikte pencereden çıkan freebies: auth çerçevesi, oturumlar çerçevesi, admin arayüzü, elbette pek çok şey.
  • Mongo'nun referanslama yeteneklerini (birden fazla sorgu gerektiren) kullanmalı veya verileri denormalize etmelidir. Sadece Django’dan aldığımız freebiesleri kaybetmekle kalmıyor, aynı zamanda PostgreSQL’de aldığımız JOIN'ler gibi freebiesleri de kaybediyoruz.
  • Veri güvenliği Birisi MongoDB'yi okuduğunda, nasıl olacağına ve verilerinizi kaybedeceğine dair en az bir kişi olduğu anlaşılıyor. Asla belirli bir olaydan söz etmiyorlar ve hepsi sadece hogwash olabilir ya da sadece eski varsayılan ateşle ilgili olabilir ve yazma kaygısını unutabilir, ama yine de beni endişelendiriyor. Elbette her durumda oldukça paranoyak bir yedekleme stratejisi kullanacağız (eğer veriler sessizce bozulursa elbette önemsiz olabilir ...).

5. PostgreSQL ve MongoDB

İlişkisel veriler ilişkisel veri tabanına, belge verileri ise doküman odaklı veri tabanına gider. documentsİlişkisel veritabanı üzerinde tablo biz belgeler üzerinde alanların asıl değerleri için sorguya gerektiğinde kullanacağımız biz indeksi veya dilim ve zar gerekebilir veri yanı sıra MongoDB objectId tümünü içerir. ORM'yi veya yerleşik yöneticiyi, belgelerin değerleri için kullanamadık ancak bu, tüm uygulamanın temelde belgeler için yönetici bir arayüz olması ve büyük olasılıkla zorunda kalmamız gerektiği için, çok büyük bir kayıp değil. ORM'nin belirli bir bölümünü, tam ihtiyacımız olan şekilde çalışmasını sağlamak için kabul edilemez bir dereceye kadar özelleştirin.

Avantajları:

  • Her arka uç sadece iyi olanı yapar.
  • Modeller arasındaki referanslar, birden fazla sorgu gerektirmeden korunur.
  • Django'nun bize verdiği, kullanıcı, oturum vb.
  • documentsNe kadar farklı belge sınıfı oluşturulduğundan bağımsız olarak yalnızca bir tabloya ihtiyacınız var .
  • Daha az sıklıkla sorgulanan belge verileri, daha sık sorgulanan meta verilerden güçlü bir şekilde ayrılır.

Dezavantajları:

  • Belge verilerinin alınması, önce SQL DB'ye ve ardından MongoDB'ye karşı 2 sıralı sorgu gerektirecektir (yine de aynı veriler Mongo'da depolanmış ve normalleştirilmiş olmamasından daha kötü değildir).
  • Yazma artık atomik olmayacak. Tek bir Mongo belgesine karşı yazmanın atomik olduğu garanti edilir ve PG açıkça atomiklik garantileri yapabilir, ancak her ikisine de yazma atomiğinin sağlanması uygulama mantığını gerektirir, performans ve karmaşıklık cezasıyla hiç şüphe yok.
  • İki arka uç = iki sorgu dili = farklı yönetici gereksinimlerine sahip iki farklı program = bellek için iki veritabanı.

JSONVeri türü olan bir sütun için giderdim . Postgres'te yeni özellikler kullanmaktan korkmayın - Postgres ekibi kararlı olmayan özellikleri serbest bırakmaz. Ve 9.2 aslında o kadar yeni değil). Ayrıca, yeni JSON özelliklerinden 9.3'te, oradayken yararlanabilirsiniz. Belgeleri her zaman uygulama kodunuzda tam olarak işliyorsanız (daha sonra SQL kullanarak), JSON'u da normal bir textsütunda saklayabilirsiniz .
a_horse_with_no_name

Potansiyel cevaplayıcılara: Lütfen cevap vermekten çekinmeyin! Bu soru, “mükemmel” bir cevap olmadan oldukça uzun bir süredir devam ettiği için, soruyu uygulamaya koyduktan ve üretime geçtikten sonra, soruyu deneyimin tam bir postmortemiyle cevaplamak niyetindeyim. Gelecekte bir yıl olabilir, ama endişelenmeyin - OP teslim edecek. Bunun, belirli bir soruyu beğenen / onlardan hoşlananların en faydalı bulduklarını umuyorum: İşe yaradığının doğrulanması ya da barikatların yan yana hangi seçeneği öldürdüğünü açıklamak.
chucksmash

2
@chucksmash. Sonuçta # 5 ile gittin mi? Her iki db'yi nasıl uyguladınız? Hangi araçları kullandın? Hayır ise neden?
xpanta

@chucksmash Hala söz verdiğin geri bildirimleri bekliyor.
Bhashit Parikh,

@chucksmash OP yayınlamadı ... :(
Albert Rothman

Yanıtlar:


13

Bazı düşünceler....

Genellikle biri, birbiriyle sıkı sıkıya ilişkili bilgilerin parçalarını farklı sistemlerde saklamak istemez. Senkronizasyondan çıkma ihtimali çok önemlidir ve şimdi ellerinizdeki bir sorun yerine iki tane var. Mongo ile yapabileceğiniz bir şey, verilerinizi içeri veya dışarı aktarmak için kullanmaktır. Benim tercihim, PostgreSQL'deki herşeyi mümkün olduğu ölçüde saklamak. Bununla birlikte, bunu yapmanın PostgreSQL programlama konusunda uzmanlık bilgisi gerektirdiğini ve gelişmiş özellikleri kullanmaya adamak istemedikleri dükkanlar için olmadığını unutmayın. Senden biraz farklı seçenekler görüyorum. Tercihim listelenen gördüğüm bir şey olmadığı için size vereceğim.

Muhtemelen meta verilerinizi ortak verilere, sınıflar için gereken verilere ve belge verisine ayırabilirsiniz. Bu bağlamda, temel ortak bilgileri içeren genel bir katalog tablosuna ve sınıf başına bir tabloya sahip olacaksınız. Bu tabloda, önemli ölçüde sınırlandırılması gereken verileri sakladığınız sütunlarla birlikte verilerin geri kalanını depolayacak bir hstore, json veya xml alanına sahip olacaksınız. Bu, sınıf başına bu tablolara koymak gerekeni azaltır, ancak istediğiniz şekilde kısıtlamalardan yararlanmanıza izin verir. Üç seçeneğin farklı sorunları var ve ayrı ayrı düşünülmeye değer:

hstore nispeten sınırlıdır fakat aynı zamanda birçok insan tarafından da kullanılmaktadır. Son derece yeni değil ama yalnızca bir anahtar / değer deposu ve json ve xml'den farklı olarak yuvalanmış veri yapılarına sahip değil.

json oldukça yeni ve şu anda pek bir şey yapmıyor. Bu, onunla fazla bir şey yapamayacağınız anlamına gelmez, ancak kutunun dışında fazla bir şey yapmayacaksınız. Bunu yaparsanız, muhtemelen plv8js'de veya daha eski ortamlara bağlı kalmak istiyorsanız, plperlu veya plpython gibi önemli miktarda programlama yapmayı bekleyebilirsiniz. jsonen azından şu andaki geliştirme anlık görüntülerinde olsa da 9.3'te daha iyi desteklenir, bu nedenle sürüm serbest bırakıldığında işler daha iyi hale gelir.

xml , en çok özellik ve en uzun destek geçmişi olan üçün en iyi şekilde desteklenir. Sonra tekrar, bu XML .....

Bununla birlikte, Mongo ve PostgreSQL ile birlikte gitmeye karar verirseniz, PostgreSQL'in 2 aşamalı taahhüt anlamını desteklediğine dikkat edin, sonra yazma işlemlerini çalıştırabilirsiniz, sorun PREPARE TRANSACTIONve bu başarılı olursa Mongo'da atom yazınız. Bu başarılı olursa COMMITPostgreSQL de olabilirsiniz.


1
Bunların hepsi harika öneriler. Daha önce hstore / json kullanarak bahsetmiştim (ve xml'i sessizce indirdim, çünkü, iyi, xml) ama önerdiğiniz şekilde kullanmayı düşünmedim. Bütün bunların ötesinde, Postgres 2 aşaması için öneri önerisi altındır. Bunun var olduğu hakkında hiçbir fikrim yoktu. büyük öneriler için teşekkür ederiz.
chucksmash

2 aşamalı taahhüt gerçekten altındır. Bir NoSQL'in bir arada kullanılmasını çok olanaklı kılar. Özellikle 2 DB arasındaki veriler nadiren birbiriyle ilişkiliyse ve çoğunlukla farklı problemleri
çözerse

0

MongoDB ve Postgres'te bulunan verileri tek bir sorguda birleştirmek için Presto veya Dremio gibi bir sorgu motoru ayarlayabilirsiniz . Her ikisi de bu veritabanlarının her biri için bağlayıcılara sahiptir ( buradaki ve buradaki belgelere bakın ) ve sırasıyla "bir şey üzerinde SQL" çalıştırmayı ve "bir şey katılmayı" önerir.

Presto'yu test etmek için AWS EMR'ye Hadoop, Hive ve Presto (komut satırını kullanmak istemiyorsanız renk tonu ekleyin) ile küçük bir küme dağıtabilirsiniz, kutudan çalışır - ayarlamak için bu talimatları izlediğinizden emin olun konnektörleri . Kovan kesinlikle gerekli değildir, ancak onunla birlikte, Mongo ve Postgres arasındaki birleşimlerin sonucunu kullanarak tablolar oluşturabilirsiniz ( örnekler için bu sayfayı kontrol edin ). Piyasada (sözde) yoğun şekilde optimize edilmiş ve 30 günlük bir deneme süresi bulunan ücretli bir sürümü de var .

Dremio'yu kullanmadım, ancak bunu AWS, Azure veya tesislerde dağıtmanın birkaç kolay yolu var . Onlar var kendi web sitesinde bazı online kurslar ücretsiz sınıfları takip etmek için kullanabileceğiniz bir "sanal laboratuvarda" erişimi olan,.

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.