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 Document
ve 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
Document
ve 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.
documents
Ne 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ı.
JSON
Veri 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 birtext
sütunda saklayabilirsiniz .