Я работаю над хобби-проектом под названием Menu / Recipe Management.
Так выглядят мои сущности и их отношения.
А Nutrient
имеет свойства Code
иValue
Ан Ingredient
имеет коллекциюNutrients
A Recipe
имеет коллекцию Ingredients
и иногда может иметь коллекцию другихrecipes
А Meal
имеет коллекцию Recipes
иIngredients
А Menu
имеет коллекциюMeals
Отношения могут быть изображены как
На одной из страниц для выбранного меню мне нужно отобразить информацию об эффективных питательных веществах, рассчитанную на основе ее составляющих (блюда, рецепты, ингредиенты и соответствующие питательные вещества).
На данный момент я использую SQL Server для хранения данных, и я перемещаюсь по цепочке из своего кода C #, начиная с каждого приема меню и затем собирая значения питательных веществ.
Я думаю, что это неэффективный способ, так как этот расчет выполняется каждый раз, когда запрашивается страница, и составляющие время от времени меняются.
Я думал о том, чтобы иметь фоновый сервис, который поддерживает таблицу с именем MenuNutrients ( {MenuId, NutrientId, Value}
) и будет заполнять / обновлять эту таблицу эффективными питательными веществами при изменении любого компонента (еда, рецепт, ингредиент).
Я чувствую, что GraphDB будет хорошо подходить для этого требования, но мое знакомство с NoSQL ограничено.
Я хочу знать, каковы альтернативные решения / подходы к этому требованию отображения питательных веществ данного меню.
Надеюсь, мое описание сценария понятно.
источник
Ответы:
В зависимости от требований и архитектуры могут быть варианты улучшения производительности:
Вы можете использовать индексированные представления (matrialized) для повышения производительности чтения на уровне RDBMS (Sql-сервер).
По сути, все, что вам нужно сделать, это:
создать обычный вид.
Создайте кластерный индекс для этого представления .
Использование механизма обналичивания на уровне приложений повысит производительность.
Если возможно и целесообразно использовать обналичивание, вам поможет такая денежная стратегия, как синглтон ленивое обналичивание .
NoSql:
Есть много хороших статей о Sql против NoSql, таких как эта и эта
. Меня интересуют части:
где использовать NoSql:
При использовании будьте готовы к:
Помимо принятия решения использовать или не использовать NoSQL, полезные статьи о NoSQL СУБД Сравнение и намерение их можно найти здесь , как некоторые из них сосредоточены на максимуме чтений, низкие записи, карта-свертка, HA ...
Посмотрев в рейтинге и популярности их по категориям может быть полезным.
источник
На самом деле вам не нужно использовать граф db, просто храните необходимые значения на одном верхнем уровне. Это как хранить
Order
иOrderItems
. Вам не нужно рассчитывать общее количество каждый раз, когда заказ будет отображаться. Вместо этого вы просто вычисляете сумму, НДС и другие вещи и сохраняете их вместе со своимиOrder
.источник
Я предлагаю взглянуть на шаблон разделения ответственности командных запросов .
В основном, вместо создания одной модели для чтения и записи, вы можете создать 2 разные модели. Один оптимизирован для обновления, а другой оптимизирован для запросов (чтение, отчетность, ...). Эти две модели синхронизируются (обычно с возможной согласованностью) с использованием событий домена (см. DDD).
Я начал изучать эту модель несколько месяцев назад, и она действительно изменила мой способ моделирования программного обеспечения. Это нелегко, потому что это большой сдвиг, особенно при использовании с другими методами, такими как DDD и Event Sourcing. Но стоит того.
Есть много ресурсов, доступных в сети, поиск CQRS и DDD (и, в конечном итоге, Event Sourcing).
Этот шаблон можно использовать как для SQL, так и для noSql.
В вашем случае вы можете инициировать событие каждый раз, когда изменяются питательные вещества, чтобы обновить модель чтения, которая разрешена для чтения. Модель чтения может быть, например, денормализованным представлением питательных веществ меню (почему бы не использовать nosql db для эффективного чтения). Вы можете иметь несколько моделей чтения на основе запросов, которые вам нужно выполнить.
Этот подход имеет некоторые последствия, но он очень масштабируемый и расширяемый.
источник
Это во многом зависит от того, как вы получаете меню и питательные вещества на начальном этапе. Как вы думаете, почему это не будет эффективным?
Из того, что я понимаю, вы идете в БД, получаете меню, затем снова идете, получаете каждый рецепт, затем снова идете и получаете каждый ингредиент и так далее. Это действительно неэффективно, поскольку существует множество запросов и обращений к серверу, что является основным источником задержек. Это известно как проблема SELECT N + 1.
Что вам нужно сделать, это получить все данные в одном запросе, используя
JOIN
s для всех таблиц от меню до питательных веществ, чтобы сервер БД мог использовать все связи и индексы для одновременного получения данных. Клиентское приложение C # только обрабатывает и отображает конечный результат. Делать это гораздо эффективнее, чем идти один за другим.В целом, используя правильные методы запросов и правильные индексы для критических запросов, реляционные базы данных могут очень хорошо работать на больших таблицах под нагрузкой.
источник
JOIN
секунд, которые не должны быть обременительными для сервера (если мы не говорим о выборке сотен или тысяч строк), при условии правильной индексации на месте. Даже с большими наборами данных вы всегда можете построить представление для всего результата и даже индексировать представление, чтобы иметь предварительный расчет результата, если производительность когда-либо станет проблемой.Похоже, вы потратили некоторое время на размышления о том, как лучше всего моделировать данные, чтобы их можно было легко обновлять и запрашивать. Однако теперь вы находитесь в той точке, где вам нужно предоставить доступ к данным. Эти две вещи являются отдельными проблемами.
Вы упоминаете, что перезагрузка страницы вызывает новый запрос к базе данных. Вы также упоминаете, что база данных будет периодически обновляться, и когда вы хотите, чтобы эти обновления отображались на странице своевременно. Лучший способ уменьшить накладные расходы на запросы - не выполнять их. Если вы выполняете одни и те же запросы снова и снова и получаете одни и те же результаты, почему бы не кешировать их какое-то время? Вы должны быть в состоянии реализовать некоторое восходящее кэширование без изменения остальной части проекта. Я бы порекомендовал почитать про отдых, Независимо от того, реализуете ли вы проект в формате rdbms или nosql, проблемы с производительностью этого типа лучше всего решать, уменьшая количество обращений к базе данных. Скажем, у вас есть 100 запросов на один и тот же рецепт за 60 секунд. Если вы кэшируете в течение 60 секунд, то вы попадаете в базу данных только один раз, так что это в 100 раз повышает производительность. Чтобы увидеть тот же уровень улучшения при переходе на nosql, потребуется гораздо больше работы.
Системы типа Nosql могут быть отличным решением, когда у вас огромный объем данных или экстремальные требования к скорости чтения или записи. Однако эта дополнительная производительность достигается за счет отказа от таких вещей, как ссылочная целостность.
источник
Похоже, что для эксперимента или в целях знания вы хотите попробовать Graph-DB, но ваш пример явно является примером иерархических данных, где мы можем развернуть / развернуть через узел. Я не эксперт в Graph / Neo DB, но я вижу, что пользователь / вы можете запрашивать данные из этой схемы не так уж сложно. Я вижу, что выбор дизайна базы данных / схемы очень зависит от того, как и какой тип данных будет запрашиваться. Поскольку вы используете SQLSERVER "HierarchyI", D - это лучший вариант, с моей точки зрения, чтобы поместить эти узлы как часть дерева.
источник
Мое предложение - думать как машина, а не как человек. Это может показаться повторяющимся, но это то, что машины хороши. Одна вещь, которую вы должны задать себе: «Нужно ли мне в любом случае извлекать каждый объект для отображения на моей странице?» Если да, продолжайте то, что вы делаете, по сравнению с поиском данных, циклы ЦП незначительны при выполнении простой математики.
источник