Вкладені сутності та обчислення властивості сутності листів - підхід SQL або NoSQL


10

Я працюю над хобі-проектом під назвою Menu / Recipe Management.

Так виглядають мої сутності та їх відносини.

А Nutrientмає властивості CodeіValue

У Ingredientколекції єNutrients

A Recipeмає колекцію, Ingredientsа іноді може мати колекцію іншихrecipes

A Mealмає колекцію RecipesтаIngredients

A Menuмає колекціюMeals

Відносини можна зобразити як

Меню Суб'єкти та відносини

На одній зі сторінок для вибраного меню мені потрібно відобразити інформацію про ефективні поживні речовини, розраховані на основі її складових (їжі, рецепти, інгредієнти та відповідні поживні речовини).

На сьогоднішній день я використовую SQL Server для зберігання даних, і я переходжу по ланцюгу з мого коду C #, починаючи з кожного прийому їжі в меню, а потім агрегуючи значення поживних речовин.

Я думаю, що це не є ефективним способом, тому що цей розрахунок проводиться кожного разу, коли запит на сторінку і час від часу змінюються складові.

Я думав про те, щоб мати фонову службу, яка підтримує таблицю під назвою MenuNutrients ( {MenuId, NutrientId, Value}) і заповнить / оновить цю таблицю ефективними поживними речовинами, коли будь-який компонент (їжа, рецепт, інгредієнт) зміниться.

Я вважаю, що GraphDB добре підходить для цієї вимоги, але мій вплив на NoSQL обмежений.

Хочу знати, які існують альтернативні рішення / підходи до цієї вимоги відображення поживних речовин даного меню.

Сподіваюся, мій опис сценарію зрозумілий.


Скільки об’єктів ми говоримо? Чи справді виступ буде проблемою?
flop

@flup В середньому меню може мати 8 прийомів їжі, кожен прийом їжі може мати 2 рецепти та 2 інгредієнти, кожен рецепт може мати 6-8 інгредієнтів.
Чанду

Хіба ваші стрілки не в тому напрямку?
Бранко Димитріевич

Ви бачили зразок Nerd Dinner Entity Framework Framework?
Акаш Кава

Відповіді:


8

Виходячи з вимог та архітектури, можуть бути варіанти покращення продуктивності:

  • Ви можете використовувати індексовані представлення (матриалізовані) для підвищення продуктивності читання на рівні RDBMS (сервер Sql).
    В основному, все, що вам потрібно зробити: це
    створити звичайний перегляд.
    Створіть кластерний індекс у цьому поданні .

  • Використання механізму готівки на рівні додатків підвищить продуктивність.
    Якщо це можливо та реально використовувати готівку, вам допоможе така стратегія готівки, як лінгвістичний готівка в одиночку .

NoSql:
Є багато хороших статей про Sql проти NoSql, як ця, так і ця.

Ці частини мене цікавлять:

Де використовувати NoSql:

Якщо ваша БД 3NF і ви не приєднуєтесь (ви просто вибираєте купу таблиць і збираєте всі об'єкти, AKA, що робить більшість людей у ​​веб-додатку.

При використанні будьте готові до:

  • Ви закінчуєте писати завдання, щоб робити такі речі, як об'єднання даних з різних таблиць / колекцій, що RDBMS зробить для вас автоматично.
  • Ваші можливості запиту в NoSQL різко калічені. MongoDb може бути найближчим до SQL, але він все ще сильно відстає. Довірся мені. SQL-запити надзвичайно інтуїтивні, гнучкі та потужні. NoSql запитів немає.
  • Запити MongoDb можуть отримати дані лише з однієї колекції та скористатися лише одним індексом. І MongoDb - це, мабуть, одна з найбільш гнучких баз даних NoSQL. У багатьох сценаріях це означає більше зворотних поїздок на сервер для пошуку відповідних записів. І тоді ви починаєте денормалізувати дані - це означає фонові завдання.
  • Той факт, що це не реляційна база даних, означає, що ви не матимете (вважається, що хтось погано спрацьовує) зовнішніх ключових обмежень для забезпечення відповідності ваших даних. Запевняю, що врешті-решт це створить невідповідності даних у вашій базі даних. Будь готовий. Швидше за все, ви почнете писати процеси чи перевірки на відповідність своїй базі даних, що, ймовірно, не буде краще, ніж дозволити RDBMS робити це за вас.
  • Забудьте про зрілі рамки на кшталт сплячки.

Окрім того, чи вирішили використовувати чи не використовувати NoSql, тут можна знайти корисну статтю про порівняння СУБД NOSQL та їх наміри, оскільки деякі з них зосереджені на високому читанні, низькому записі, зменшенні карти, HA ...
Огляд при рейтингуванні та популярності їх за категоріями може бути корисним.


Дякуємо за деталі. Перевіримо посилання та зв’яжемось із вами.
Чанду

3

Я фактично не потрібно використовувати графік db, просто зберігайте потрібні значення в одному верхньому рівні. Це просто як зберігання Orderта OrderItems. вам не доведеться підраховувати загальну суму кожного разу, коли збирається відображатись замовлення. Натомість ви просто обчислюєте суму, ват та інші речі та зберігаєте їх із собою 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

Я пропоную переглянути схему розбиття відповідальності за запити команд .

В основному замість створення єдиної моделі для читання та запису можна створити дві різні моделі. Один оптимізований для оновлення, а другий оптимізований для запитів (читання, звітування, ...). Дві моделі синхронізуються (як правило, з можливою послідовністю), використовуючи події домену (див. DDD).

Я почав вивчати цю закономірність кілька місяців тому, і це дійсно змінило мій спосіб моделювання програмного забезпечення. Це непросто, тому що це великий зсув, особливо коли використовується з іншими методами, такими як DDD та Sourcing подій. Але варто того.

У мережі є багато ресурсів, пошук CQRS та DDD (і, зрештою, пошук подій).

Цей шаблон можна використовувати як у SQL, так і у noSql.

У вашому випадку ви можете запускати подію щоразу, коли поживні речовини змінюються для оновлення прочитаної моделі, оптимізованої для читання. Модель читання може бути, наприклад, денормалізованим видом поживних речовин меню (чому б не використовувати nosql db для ефективного зчитування). Ви можете мати кілька моделей для читання на основі запитів, які потрібно виконати.

Існують деякі наслідки використання цього підходу, але він дуже масштабований і розширюваний.


Такий підхід я розглядав, але не був впевнений у тому, як отримати дані для моделі читання (в основному, якийсь процес повинен отримати мені дані для моделі читання).
Чанду

Зазвичай модель читання оновлюється при кожній зміні. Ви повинні реалізувати інтерфейс користувача з командами (на основі завдань), а не використовувати грубі операції. Таким чином, кожна окрема команда відбивається на прочитаній моделі. Вам не потрібно виконувати інші запити. Команди проектування дозволяють системі фіксувати реальні наміри користувача.

2

Це дуже залежить від того, як ви отримуєте меню та поживні речовини спочатку. Чому, на вашу думку, це не буде ефективно?

З того, що я розумію, ви переходите до БД, отримуєте меню, потім переходите знову, отримуєте кожен рецепт, потім переходите знову і отримуєте кожен інгредієнт тощо. Це дійсно неефективно, оскільки існує багато запитів та зворотних поїздок на сервер, що є основним джерелом затримок. Це відоме як проблема SELECT N + 1.

Що потрібно зробити, це отримати всі дані в одному запиті, використовуючи JOINs для всіх таблиць з меню до поживних речовин, тому сервер БД може використовувати всі зв’язки та індекси, щоб отримати дані відразу. Додаток C # клієнта лише обробляє та відображає кінцевий результат. Робити це набагато ефективніше, ніж йти один за одним.

Взагалі, використовуючи належні методи запитів та правильні індекси для критичних запитів, реляційні бази даних можуть дуже добре працювати на великих таблицях під навантаженням.


Дякую, я розумію, що це залежить від приєднань. Оскільки складові меню періодично змінюються, я не хочу запускати обчислення кожного разу, коли хтось потрапляє на сторінку. Натомість я хочу, щоб фоновий сервіс здійснив обчислення, і я можу просто прочитати його з таблиці, коли це необхідно. Проблема з розрахунком полягає у визначенні всього ланцюга, коли змінюється одна із складових.
Чанду

Просто пошук кількох відносин взагалі не несе жодного обчислення, навіть якщо є 5 або 6 JOINс, що не повинно бути тягарем для сервера (якщо ми не говоримо про отримання сотень чи тисяч рядків), якщо належна індексація стоїть на місці. Навіть із великими наборами даних ви завжди можете створити перегляд всього результату і навіть індексувати подання, щоб результат був заздалегідь підрахований, якщо ефективність коли-небудь стане проблемою.

2

Схоже, ви витратили деякий час на роздуми про те, як найкраще моделювати дані, щоб їх можна було легко оновлювати та запитувати. Однак зараз ви перебуваєте на місці, коли вам потрібно забезпечити доступ до даних. Ці дві речі - це окрема проблема.

Ви згадуєте, що перезавантаження сторінки викликає новий запит до бази даних. Ви також згадуєте, що база даних буде періодично оновлюватися, і коли ви хочете, щоб ці оновлення відображалися на сторінці своєчасно. Найкращий спосіб зменшити накладні запити - це не виконувати їх. Якщо ви повторно повторюєте однакові запити і отримуєте однакові результати, чому б не кешувати їх на деякий час? Ви повинні мати змогу реалізувати кешування кількох потоків без зміни решти проекту. Я б рекомендував прочитати про відпочинок. Незалежно від того, якщо ви реалізуєте проект у форматі rdbms або nosql з роботою цього типу, найкраще вирішувати, зменшуючи кількість разів, коли вам доведеться перейти до бази даних. Скажіть, у вас є 100 запитів на той самий рецепт за 60 секунд. Якщо ви кешуєте протягом 60 секунд, ви натискаєте базу даних лише один раз, так що це 100-кратне підвищення продуктивності. Щоб побачити той самий рівень покращення, перейшовши на nosql, потрібно буде набагато більше роботи.

Системи типу Nosql можуть бути чудовим рішенням, коли у вас є величезна кількість даних або екстремальні вимоги швидкості читання або запису. Однак додаткова продуктивність виходить за рахунок викидання таких речей, як референтна цілісність.


1

Схоже, для експерименту чи знань ви хочете спробувати Graph-DB, але ваш приклад - це явно приклад ієрархічних даних, де ми можемо прокручувати / вгору через вузол. Я не є експертом по Graph / Neo DB, але я можу побачити, що в способі користувача / ви можете вимагати даних за допомогою цієї схеми не так вже й багато складності. Я бачу, вибір дизайну бази даних / схеми дуже залежить від того, як і який тип даних буде запитуватися проти неї. Оскільки ви використовуєте SQLSERVER, "ІєрархіяI" D - це найкращий варіант з моєї точки зору, щоб розмістити ці вузли як частину Дерева.


1

Моя пропозиція - думати як машина, а не як людина. Це може здатися повторюваним, але те, що в машинах добре. Одне, що ви повинні запитати у себе, це "чи я мушу все-таки отримати кожен об'єкт, щоб відобразити на своїй сторінці?" Якщо так, продовжуйте те, що ви робите, порівняно із пошуком даних, цикли процесорів незначні при виконанні простої математики.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.