Entitas bersarang dan perhitungan pada properti entitas daun - Pendekatan SQL atau NoSQL


10

Saya sedang mengerjakan proyek hobi yang disebut Menu / Recipe Management.

Beginilah rupa entitas saya dan relasinya.

A Nutrientmemiliki properti CodedanValue

An Ingredientmemiliki koleksiNutrients

A Recipememiliki Koleksi Ingredientsdan kadang-kadang dapat memiliki koleksi lainnyarecipes

A Mealmemiliki Koleksi RecipesdanIngredients

A Menumemiliki KoleksiMeals

Relasi dapat digambarkan sebagai

Entitas dan Hubungan Menu

Di salah satu halaman, untuk menu yang dipilih, saya perlu menampilkan informasi nutrisi yang efektif yang dihitung berdasarkan unsur-unsurnya (Makanan, Resep, Bahan dan nutrisi yang sesuai).

Sampai sekarang saya menggunakan SQL Server untuk menyimpan data dan saya menavigasi rantai dari kode C # saya, mulai dari setiap makan menu dan kemudian mengumpulkan nilai nutrisi.

Saya pikir ini bukan cara yang efisien karena perhitungan ini dilakukan setiap kali halaman diminta dan konstituen berubah sesekali.

Saya sedang berpikir tentang memiliki layanan latar belakang yang memelihara tabel yang disebut MenuNutrients ( {MenuId, NutrientId, Value}) dan akan mengisi / memperbarui tabel ini dengan nutrisi yang efektif ketika salah satu komponen (Makanan, Resep, Bahan) perubahan.

Saya merasa bahwa GraphDB akan cocok untuk persyaratan ini, tetapi paparan saya ke NoSQL terbatas.

Saya ingin tahu apa alternatif solusi / pendekatan untuk persyaratan ini menampilkan nutrisi dari menu yang diberikan.

Semoga uraian saya tentang skenario ini jelas.


Berapa banyak objek yang kita bicarakan? Akankah kinerja benar-benar menjadi masalah?
flup

@ flup Rata-rata Menu dapat memiliki 8 kali makan, setiap kali makan dapat memiliki 2 resep dan 2 bahan, setiap resep dapat memiliki 6-8 bahan.
Chandu

Bukankah panahmu ada di arah yang salah?
Branko Dimitrijevic

Pernahkah Anda melihat sampel Nerd Dinner Entity Framework?
Akash Kava

Jawaban:


8

Berdasarkan persyaratan dan arsitektur, mungkin ada opsi peningkatan kinerja:

  • Anda dapat menggunakan tampilan yang diindeks (matrialized) Untuk meningkatkan kinerja membaca pada tingkat RDBMS (Sql server).
    Pada dasarnya, yang perlu Anda lakukan adalah:
    Buat tampilan biasa.
    Buat indeks berkerumun pada tampilan itu .

  • Menggunakan mekanisme pencairan di tingkat aplikasi akan meningkatkan kinerja.
    Jika memungkinkan dan layak untuk menggunakan pencairan, memiliki strategi tunai seperti pencairan malas tunggal akan membantu Anda.

NoSql:
Ada banyak artikel bagus tentang Sql vs NoSql, seperti ini dan ini

Bagian menarik bagi saya:

Di mana harus menggunakan NoSql:

Jika DB Anda adalah 3NF dan Anda tidak melakukan penggabungan (Anda hanya memilih banyak tabel dan menyatukan semua objek, AKA apa yang dilakukan kebanyakan orang di aplikasi web.

Saat digunakan siap untuk:

  • Anda akhirnya menulis pekerjaan untuk melakukan hal-hal seperti menggabungkan data dari berbagai tabel / koleksi, sesuatu yang akan dilakukan RDBMS untuk Anda secara otomatis.
  • Kemampuan kueri Anda dengan NoSQL lumpuh secara drastis. MongoDb mungkin merupakan hal yang paling dekat dengan SQL tetapi masih sangat jauh di belakang. Percayalah kepadaku. Query SQL sangat intuitif, fleksibel dan kuat. Kueri NoSql tidak.
  • Kueri MongoDb dapat mengambil data hanya dari satu koleksi dan memanfaatkan hanya satu indeks. Dan MongoDb mungkin adalah salah satu dari database NoSQL yang paling fleksibel. Dalam banyak skenario, ini berarti lebih bolak-balik ke server untuk menemukan catatan terkait. Dan kemudian Anda mulai menonaktifkan data - yang berarti pekerjaan latar belakang.
  • Fakta bahwa itu bukan database relasional berarti bahwa Anda tidak akan memiliki (kunci oleh beberapa orang berkinerja buruk) kendala kunci asing untuk memastikan bahwa data Anda konsisten. Saya yakinkan Anda bahwa ini pada akhirnya akan menciptakan inkonsistensi data dalam database Anda. Dipersiapkan. Kemungkinan besar Anda akan mulai menulis proses atau memeriksa agar database Anda konsisten, yang mungkin tidak akan berkinerja lebih baik daripada membiarkan RDBMS melakukannya untuk Anda.
  • Lupakan kerangka kerja yang matang seperti hibernate.

Selain memutuskan untuk menggunakan atau tidak menggunakan NoSql, artikel bermanfaat tentang NOSQL DBMS Comparison dan niat mereka dapat ditemukan di sini karena beberapa dari mereka berfokus pada membaca tinggi, menulis rendah, mengurangi peta, HA ...
Melihat-lihat di peringkat dan popularitas mereka , berdasarkan kategori mungkin berguna.


Terima kasih untuk detailnya. Akan memeriksa tautan dan kembali kepada Anda.
Chandu

3

Saya sebenarnya Anda tidak perlu menggunakan grafik db, cukup simpan nilai yang diperlukan dalam satu tingkat atas. Ini seperti menyimpan Orderdan OrderItems. Anda tidak harus menghitung total setiap kali pesanan akan ditampilkan. Sebaliknya Anda hanya menghitung jumlah, tong dan barang-barang lainnya dan menyimpannya dengan 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

Saya menyarankan untuk melihat pola Segregasi Command Query Responsibility .

Pada dasarnya, alih-alih membuat model tunggal untuk membaca dan menulis, Anda dapat membuat 2 model berbeda. Satu dioptimalkan untuk memperbarui dan yang lainnya dioptimalkan untuk kueri (baca, pelaporan, ...). 2 model disinkronkan (biasanya dengan konsistensi akhirnya) menggunakan peristiwa domain (lihat DDD).

Saya mulai mempelajari pola ini beberapa bulan yang lalu dan itu benar-benar mengubah cara saya memodelkan perangkat lunak. Ini tidak mudah karena ini adalah perubahan besar, terutama bila digunakan dengan teknik lain seperti DDD dan Event Sourcing. Tapi sepadan dengan itu.

Ada banyak sumber daya yang tersedia di internet, cari CQRS dan DDD (dan akhirnya Event Sourcing).

Pola ini dapat digunakan pada SQL dan noSql.

Dalam kasus Anda, Anda dapat menjalankan suatu peristiwa setiap kali nutrisi diubah untuk memperbarui model baca yang dioptimalkan untuk dibaca. Model baca dapat misalnya tampilan denormalized dari nutrisi menu (mengapa tidak menggunakan nosql db untuk pembacaan yang efisien). Anda dapat memiliki beberapa model baca berdasarkan kueri yang perlu Anda lakukan.

Ada beberapa implikasi menggunakan pendekatan ini tetapi sangat terukur dan dapat dikembangkan.


Ini adalah pendekatan yang saya renungkan, tetapi tidak yakin tentang cara mendapatkan data untuk model baca (pada dasarnya beberapa proses seharusnya memberi saya data untuk model baca).
Chandu

Biasanya model baca diperbarui pada setiap perubahan. Anda harus mengimplementasikan ui dengan perintah (berbasis tugas) alih-alih menggunakan operasi crud. Dengan cara ini setiap perintah tercermin pada model read. Anda tidak perlu menjalankan kueri lain. Merancang perintah memungkinkan sistem untuk menangkap maksud sebenarnya dari pengguna.

2

Ini sangat tergantung pada bagaimana Anda melakukannya untuk mendapatkan menu dan nutrisi pada awalnya. Menurut Anda mengapa itu tidak efisien?

Dari apa yang saya mengerti, Anda pergi ke DB, dapatkan menu, lalu pergi lagi, dapatkan setiap resep, lalu pergi lagi dan dapatkan masing-masing bahan dan sebagainya. Ini benar-benar tidak efisien, karena ada banyak pertanyaan dan bolak-balik ke server, yang merupakan sumber utama keterlambatan. Ini dikenal sebagai masalah SELECT N +1.

Apa yang harus Anda lakukan adalah mengambil semua data dalam satu kueri, dengan menggunakan JOINs untuk semua tabel dari menu hingga nutrisi, sehingga server DB dapat menggunakan semua hubungan dan indeks untuk mendapatkan data sekaligus. Aplikasi klien C # hanya memproses dan menampilkan hasil akhir. Melakukannya jauh lebih efisien daripada melakukannya satu per satu.

Secara umum, menggunakan teknik kueri yang tepat dan indeks yang tepat untuk kueri kritis, basis data relasional dapat berkinerja sangat baik pada tabel besar yang sedang dimuat.


Terima kasih, saya mengerti bahwa itu tergantung pada gabungan. Karena konstituen menu berubah kadang-kadang saya tidak ingin menjalankan perhitungan setiap kali ada yang menyentuh halaman. Alih-alih, saya ingin layanan latar belakang untuk melakukan perhitungan dan saya bisa membacanya dari sebuah tabel saat dibutuhkan. Masalah dengan perhitungan adalah mengidentifikasi seluruh rantai ketika salah satu konstituen berubah.
Chandu

Hanya mencari beberapa hubungan tidak menimbulkan perhitungan sama sekali, bahkan jika ada 5 atau 6 JOINyang seharusnya tidak menjadi beban pada server (kecuali jika kita berbicara tentang mengambil ratusan atau ribuan baris), jika pengindeksan yang tepat ada di tempat. Bahkan dengan kumpulan data besar, Anda selalu dapat membangun tampilan pada seluruh hasil, dan bahkan mengindeks tampilan untuk memiliki hasil yang dihitung sebelumnya, jika kinerja pernah menjadi masalah.

2

Sepertinya Anda telah menghabiskan waktu memikirkan cara terbaik untuk memodelkan data sehingga dapat dengan mudah diperbarui dan ditanya. Namun, sekarang Anda berada pada titik di mana Anda perlu menyediakan akses ke data. Kedua hal itu merupakan masalah tersendiri.

Anda menyebutkan memuat ulang halaman menyebabkan kueri baru ke database. Anda juga menyebutkan bahwa basis data sesekali akan diperbarui dan ketika Anda menginginkan pembaruan itu ditampilkan pada halaman secara tepat waktu. Metode terbaik Anda untuk mengurangi overhead kueri adalah tidak melakukannya. Jika Anda menjalankan kueri yang sama berulang-ulang dan mendapatkan hasil yang sama, mengapa tidak menyimpannya untuk sementara waktu? Anda harus dapat mengimplementasikan beberapa caching di bagian hulu tanpa mengubah sisa proyek. Saya akan merekomendasikan membaca tentang istirahat. Terlepas dari apakah Anda mengimplementasikan proyek dalam masalah rdbms atau nosql dengan kinerja jenis ini yang terbaik ditangani dengan mengurangi berapa kali Anda harus pergi ke database. Katakanlah Anda memiliki 100 permintaan untuk resep yang sama dalam 60 detik. Jika Anda melakukan cache selama 60 detik maka Anda hanya perlu menekan database sekali jadi itu adalah peningkatan kinerja 100x. Untuk melihat tingkat peningkatan yang sama dengan beralih ke nosql akan membutuhkan lebih banyak pekerjaan.

Sistem tipe Nosql dapat menjadi solusi yang bagus ketika Anda memiliki data dalam jumlah besar atau persyaratan kecepatan baca atau tulis yang ekstrem. Namun kinerja tambahan itu datang dengan biaya membuang hal-hal seperti integritas referensial.


1

Sepertinya untuk percobaan atau tujuan pengetahuan Anda ingin mencoba Graph-DB tetapi contoh Anda jelas merupakan contoh data hierarkis di mana kami dapat menelusuri-turun / naik melalui sebuah node. Saya bukan ahli Grafik / Neo DB namun saya bisa melihat tidak ada banyak kerumitan dalam cara pengguna / Anda dapat meminta data dari skema ini. Saya melihat pilihan desain database / skema sangat tergantung pada bagaimana dan tipe data apa yang akan dipertanyakan. Saat Anda menggunakan SQLSERVER "HierarchyI" D adalah pilihan terbaik dari sudut pandang saya untuk meletakkan node ini sebagai bagian dari Tree.


1

Saran saya adalah berpikir seperti mesin dan bukan seperti manusia. Ini mungkin terlihat berulang-ulang, tetapi mesin apa yang bagus. Satu hal yang harus Anda tanyakan pada diri sendiri adalah "apakah saya harus mengambil setiap objek, untuk ditampilkan di halaman saya?" Jika ya, lanjutkan apa yang Anda lakukan, dibandingkan dengan pengambilan data, siklus cpu dapat diabaikan saat melakukan matematika sederhana.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.