Yuvalanmış Varlıklar ve yaprak varlık özelliğinde hesaplama - SQL veya NoSQL yaklaşımı


10

Menü / Reçete Yönetimi adlı bir hobi projesi üzerinde çalışıyorum.

Varlıklarım ve ilişkileri böyle görünüyor.

A'nın Nutrientözellikleri CodeveValue

Bir Ingredientkoleksiyonu varNutrients

A'nın Recipebir Koleksiyonu vardır Ingredientsve bazen başka bir koleksiyona sahip olabilirrecipes

Bir Mealbir Koleksiyonu sahiptir RecipesveIngredients

A'nın Menukoleksiyonu varMeals

İlişkiler şu şekilde tasvir edilebilir:

Menü Varlıkları ve İlişkileri

Sayfalardan birinde, seçilen bir menü için bileşenlerine (Yemekler, Tarifler, Malzemeler ve ilgili besin maddeleri) dayalı olarak hesaplanan etkili besin bilgilerini göstermem gerekiyor.

Şu andan itibaren verileri saklamak için SQL Server kullanıyorum ve menünün her öğünden başlayıp daha sonra besin değerlerini toplayarak zinciri C # kodumdan dolaşıyorum.

Bu hesaplama, sayfa her istendiğinde ve bileşenlerin ara sıra değiştiği için yapıldığından, bunun etkili bir yol olmadığını düşünüyorum.

Ben MenuNutrients ( {MenuId, NutrientId, Value}) adlı bir tablo korur ve bileşen (Yemek, yemek tarifi, madde) herhangi bir değişiklik olduğunda bu tablo etkili besinler ile güncelleme olacak bir arka plan hizmeti sahip düşünüyordum .

Bir GraphDB bu gereksinim için iyi bir seçim olacağını hissediyorum, ancak NoSQL maruz kalma sınırlı.

Belirli bir menünün besin maddelerini göstermenin bu gereksinimine alternatif çözümlerin / yaklaşımların ne olduğunu bilmek istiyorum.

Umarım senaryo tanımım açıktır.


Kaç nesneden bahsediyoruz? Performans gerçekten bir sorun olacak mı?
flup

@flup Ortalama bir menüde 8 öğün yemek olabilir, her öğünde 2 tarif ve 2 bileşen bulunabilir, her tarif 6-8 bileşen içerebilir.
Chandu

Oklarınız yanlış yönde değil mi?
Branko Dimitrijevic

Nerd Dinner Entity Framework örneğini gördünüz mü?
Akash Kava

Yanıtlar:


8

Gereksinimlere ve mimariye bağlı olarak, performans iyileştirme seçenekleri olabilir:

  • RDBMS (Sql sunucusu) düzeyinde okuma performansını artırmak için dizine alınmış görünümleri (matrialized) kullanabilirsiniz . Temel olarak, yapmanız gereken tek şey: Düzenli bir görünüm oluşturmak. Bu görünümde kümelenmiş bir dizin oluşturun .



  • Uygulama düzeyinde bir nakit verme mekanizması kullanmak performansı artıracaktır.
    Nakit kullanımı mümkün ve mümkünse, singleton tembel nakit gibi bir nakit stratejisine sahip olmak size yardımcı olacaktır.

NoSql:
Sql vs NoSql hakkında birçok iyi makale var, bu ve bu

Parçalar ilgimi

çekiyor: NoSql nerede kullanılır:

DB ise 3NF ve herhangi katılır yapmayın (eğer insanların çoğu bir web uygulaması yapmak AKA ne sadece bir sürü tabloları seçerek ve tüm nesneleri araya koyuyorlar.

Kullanıldığında hazır olun:

  • Bir RDBMS'nin sizin için otomatik olarak yapacağı, farklı tablolardan / koleksiyonlardan verilere katılma gibi şeyler yapmak için işleri yazıyorsunuz.
  • NoSQL ile sorgu yetenekleriniz büyük ölçüde sakatlanmıştır. MongoDb, SQL'e en yakın şey olabilir, ancak yine de son derece geride. Güven Bana. SQL sorguları süper sezgisel, esnek ve güçlüdür. NoSql sorguları değildir.
  • MongoDb sorguları yalnızca bir koleksiyondan veri alabilir ve yalnızca bir dizinden yararlanabilir. Ve MongoDb muhtemelen en esnek NoSQL veritabanlarından biridir. Birçok senaryoda bu, ilgili kayıtları bulmak için sunucuya daha fazla gidiş-dönüş anlamına gelir. Ve sonra verileri normalleştirmeye başlarsınız - bu da arka plan işleri anlamına gelir.
  • İlişkisel bir veritabanı olmaması, verilerinizin tutarlı olmasını sağlamak için (bazılarının kötü performans gösterdiği düşünülür) yabancı anahtar kısıtlamalarına sahip olmayacağınız anlamına gelir. Bunun sonunda veritabanınızda veri tutarsızlıkları oluşturacağından eminim. Hazır ol. Büyük olasılıkla, veritabanınızı tutarlı tutmak için işlemler veya denetimler yazmaya başlayacaksınız, bu da RDBMS'nin sizin için yapmasına izin vermekten daha iyi performans göstermeyecektir.
  • Hazırda bekletme gibi olgun çerçeveleri unutun.

NoSQL, üzerinde yararlı bir yazı kullanmak için kullanıp kullanmayacağına karar yanında burada bulunamadı NoSQL DBMS Karşılaştırma ve bunların niyeti bazıları, düşük yazıyor, HA map-azaltmak okur en yüksek odaklanmış olarak ...
bir göz olması bunların sıralamasında ve popülaritesinde, kategoriye göre yararlı olabilir.


Detaylar için teşekkürler. Bağlantıları kontrol edip size geri dönecek.
Chandu

3

Aslında bir grafik db kullanmanıza gerek yok, sadece bir üst düzeyde gerekli değerleri saklayın. Tıpkı bir Orderve OrderItems. bir siparişin görüntüleneceği her seferinde toplamı hesaplamanıza gerek yoktur. Bunun yerine, sadece toplamı, kdv ve diğer şeyleri hesaplar ve bunları ile saklarsınız Order.

order.Subtotal = order.Items.Sum(item => item.Price);
order.Tax = order.Subtotal * 0.25m; // just a value
order.Total = order.Subtotal + order.Tax;

// fast forward time
var subTotal = order.Items.Sum(item => item.Price);
var tax = subTotal * 0.25m;
var total = subTotal + tax;

if (toal == order.Total) {
   Console.Log("Why the hell I've just re-calculated total?");
}

3

Komut Sorgusu Sorumluluk Ayrımı modeline bakmanızı öneririm .

Temel olarak okumak ve yazmak için tek bir model oluşturmak yerine 2 farklı model oluşturabilirsiniz. Biri güncelleme için optimize edilmiş ve diğeri sorgular için optimize edilmiştir (okuma, raporlama, ...). İki model, etki alanı olayları (bkz. DDD) kullanılarak senkronize edilir (genellikle nihai tutarlılıkla).

Birkaç ay önce bu modeli incelemeye başladım ve yazılım modelleme yöntemimi gerçekten değiştirdi. Kolay değil çünkü özellikle DDD ve Event Sourcing gibi diğer tekniklerle kullanıldığında büyük bir değişim. Ama buna değer.

İnternette pek çok kaynak var, CQRS ve DDD (ve sonuç olarak Olay Sağlama) için arama yapın.

Bu desen hem SQL hem de noSql'de kullanılabilir.

Sizin durumunuzda, okuma için optimize edilen okuma modelini güncellemek için besinler her değiştiğinde bir olayı başlatabilirsiniz. Okuma modeli, örneğin menünün besin maddelerinin denormalize edilmiş bir görünümü olabilir (neden etkili okuma için nosql db kullanmıyorsunuz). Gerçekleştirmeniz gereken sorgulara dayalı olarak birden fazla okuma modeline sahip olabilirsiniz.

Bu yaklaşımı kullanmanın bazı sonuçları vardır, ancak çok ölçeklenebilir ve genişletilebilir.


Bu, düşündüğüm yaklaşımdı, ancak okuma modeli için verilerin nasıl elde edileceğinden emin değildi (temel olarak bazı süreçler bana okuma modeli için verileri almalıdır).
Chandu

Genellikle okuma modeli her değişiklikte güncellenir. Ui'yi crud işlemleri yerine komutlarla (göreve dayalı) uygulamanız gerekir. Bu şekilde her komut okuma modeline yansıtılır. Başka sorgular yürütmenize gerek yoktur. Komut tasarlamak, sistemin kullanıcının gerçek amacını yakalamasını sağlar.

2

Başlangıçta menüleri ve besinleri nasıl alacağınıza bağlıdır. Sizce neden verimli olmayacak?

Anladığım kadarıyla, DB'ye gidersiniz, menüyü alırsınız, sonra tekrar gidersiniz, her tarifi alırsınız, sonra tekrar gidersiniz ve her malzemeyi alırsınız. Ana gecikme kaynağı olan sunucuya çok sayıda sorgu ve gidiş-dönüş olduğu için bu gerçekten verimsizdir. Bu SELECT N + 1 problemi olarak bilinir.

Yapmanız gereken JOIN, menüden besinlere kadar tüm tablolar için s kullanarak tek bir sorgudaki tüm verileri almaktır, böylece DB sunucusu verileri bir kerede almak için tüm ilişkileri ve dizinleri kullanabilir. İstemci C # uygulaması yalnızca nihai sonucu işler ve görüntüler. Bunu tek tek yapmaktan çok daha verimlidir.

Genel olarak, kritik sorgulamalar için uygun sorgulama teknikleri ve doğru dizinler kullanılarak ilişkisel veritabanları yük altındaki büyük tablolarda çok iyi performans gösterebilir.


Teşekkürler, bunun birleşimlere bağlı olduğunu anlıyorum. Menünün bileşenleri zaman zaman değiştiğinden, bazıları sayfaya her bastığında hesaplamayı çalıştırmak istemiyorum. Bunun yerine hesaplamayı yapmak için bir arka plan hizmeti istiyorum ve gerektiğinde basitçe bir tablodan okuyabilirim. Hesaplamayla ilgili sorun, kuruculardan biri değiştiğinde tüm zinciri tanımlamaktır.
Chandu

Sadece birkaç ilişki aramak JOIN, sunucuda bir yük olmaması gereken 5 veya 6 sn olsa bile (yüzlerce veya binlerce satır getirmekten söz etmiyorsak), herhangi bir hesaplama yapılmasına neden olmaz. yerinde. Büyük veri kümelerinde bile, her zaman tüm sonuç hakkında bir görünüm oluşturabilir ve hatta performans bir sorun haline gelirse, sonucu önceden hesaplamak için görünümü dizine ekleyebilirsiniz.

2

Kolayca güncellenip sorgulanabilmesi için verilerin en iyi nasıl modelleneceğini düşünmek için biraz zaman harcadığınız anlaşılıyor. Ancak, şimdi verilere erişim sağlamanız gereken noktadasınız. Bu iki şey ayrı endişeler.

Sayfayı yeniden yüklemenin veritabanında yeni bir sorguya neden olduğunu belirtiyorsunuz. Ayrıca veritabanının zaman zaman güncelleneceğini ve bu güncellemelerin sayfada zamanında görüntülenmesini istediğinizi de belirtmişsinizdir. Sorguların yükünü azaltmak için en iyi yöntem bunları yapmak değildir. Aynı sorguları tekrar tekrar çalıştırıyorsanız ve aynı sonuçları alıyorsanız, bunları neden bir süre önbelleğe almıyorsunuz? Projenin geri kalanını değiştirmeden akış yukarı bazı önbellekleme uygulayabilmelisiniz. Dinlenme hakkında okumanızı tavsiye ederim. Ne olursa olsun projeyi bir rdbms veya nosql bu tür performans ile uygularsanız en iyi veritabanına gitmek zorunda kaç kez azaltarak ele alınır. Aynı tarif için 60 saniyede 100 isteğiniz olduğunu varsayalım. 60 saniye önbellek kullanırsanız, veritabanına yalnızca bir kez vurursunuz. Nosql'e geçerek aynı seviyedeki iyileşmeyi görmek çok daha fazla iş gerektirecektir.

Nosql tipi sistemler, çok miktarda veri veya aşırı okuma veya yazma hızı gereksinimleriniz olduğunda harika bir çözüm olabilir. Bununla birlikte, ekstra performans, referans bütünlüğü gibi şeyleri ortaya çıkarma maliyetine sahiptir.


1

Graph-DB'yi denemek istediğiniz deney veya bilgi amacı gibi görünüyor, ancak örneğiniz açıkça bir düğüm yoluyla Detaylandırma / Artırma yapabileceğimiz hiyerarşik verilere bir örnektir. Graph / Neo DB konusunda uzman değilim ancak kullanıcının / bu şemadan veri talep edebilme biçiminde çok fazla karmaşıklık olmadığını görebilirsiniz. Veritabanı / şema tasarımının seçiminin çok ve ona karşı ne tür verilerin sorgulanacağına bağlı olduğunu görüyorum. SQLSERVER kullanırken "HierarchyI" D benim açımdan bu düğümleri Tree'nin bir parçası olarak koymak için en iyi seçenektir.


1

Benim önerim insan gibi değil bir makine gibi düşünmektir. Tekrarlayan gibi görünebilir, ancak makinelerin iyi olduğu şey. Kendinize sormanız gereken bir şey, "Sayfamda görüntülemek için her nesneyi almam gerekiyor mu?" Evet ise, basit matematik yaparken cpu döngüleri ihmal edilebilir.

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.