Предпочтительный способ получения строки с несколькими связанными строками - PullRequest
0 голосов
/ 07 февраля 2010

В настоящее время я пишу DAL на C # с помощью SqlDataReader и хранимых процедур. Производительность важна, но все же должна быть ремонтопригодной ...

Допустим, есть таблица рецептов

(recipeID, author, timeNeeded, yummyFactor, ...)

и стол ингредиентов

(recipeID, name, amount, yummyContributionFactor, ...)

Теперь я хотел бы запросить около 200 рецептов с их ингредиентами. Я вижу следующие возможности:

  • Запросите все рецепты, затем запросите ингредиенты для каждого рецепта.
    Это, конечно, приведет к большим запросам.
  • Запросите все рецепты и их ингредиентов в большом объединенном списке. Это приведет к большому количеству бесполезного трафика, потому что данные каждого рецепта будут передаваться несколько раз.
  • Запросите все рецепты, затем запросите все ингредиенты одновременно, передав список идентификаторов рецептов обратно в базу данных. Или же выполните оба запроса в одном и вернуть несколько результирующих наборов. Вернувшись в DAL, свяжите ингредиенты с рецептами по их recipeID.
  • Экзотический способ: наведите курсор на все рецепты и верните для каждого рецепта двух отдельных наборов результатов для рецепта и ингредиентов. Есть ли предел для результатов?

Для большего разнообразия рецепты могут быть выбраны по списку идентификаторов из DAL или по некоторому параметризованному условию SQL.

Какой из них, по вашему мнению, имеет лучшее соотношение производительность / беспорядок?

Ответы [ 5 ]

2 голосов
/ 07 февраля 2010

Если вам нужно объединить только две таблицы, а «ингредиент» - это не огромный объем данных, наилучшим балансом производительности и удобства обслуживания, вероятно, будет один объединенный запрос. Да, вы повторяете некоторые данные в результатах, но если у вас нет 100 000 строк, и это не перегружает сервер / сеть базы данных, слишком рано для оптимизации.

История немного отличается, если у вас много слоев объединений, каждый с уменьшением количества элементов. Например, в одном из моих приложений у меня есть что-то вроде следующего:

Event -> EventType -> EventCategory
                   -> EventPriority
                   -> EventSource   -> EventSourceType -> Vendor

Такой запрос приводит к значительному дублированию * значительного , что недопустимо, когда требуется извлечь 100 тыс. Событий, 1000 типов событий, возможно, 10 категорий / приоритетов, 50 источников и 5 поставщиков. Так что в этом случае у меня есть хранимая процедура, которая возвращает несколько наборов результатов:

  • Все 100 тыс. Событий только с EventTypeID
  • 1000 типов событий с CategoryID, PriorityID и т. Д., Которые применяются к этим событиям
  • 10 EventCategories и EventPriorities, которые применяются к вышеупомянутым EventTypes
  • 50 источников событий, сгенерировавших 100 000 событий
  • И так, вы поняли.

Поскольку количество элементов резко снижается, гораздо быстрее загрузить только то, что здесь необходимо, и использовать несколько словарей на стороне клиента, чтобы собрать их вместе (если это даже необходимо). В некоторых случаях данные с низким уровнем мощности могут даже кэшироваться в памяти и вообще никогда не извлекаться из базы данных (кроме запуска приложения или изменения данных).

Определяющими факторами при использовании такого подхода являются очень большое количество результатов и крутое снижение количества элементов для объединений, другими словами включение . Это на самом деле противоположно большинству обычаев и, вероятно, противоположно тому, что вы здесь делаете. Если вы выбираете «рецепты» и присоединяетесь к «ингредиентам», вы, вероятно, разворачиваете , что может сделать этот подход бесполезным, особенно если есть только две таблицы для объединения.

Так что я просто говорю, что это возможная альтернатива , если производительность станет проблемой в будущем; на этом этапе вашего проекта, прежде чем вы получите реальные данные о производительности, я бы просто пошел по пути использования единого объединенного набора результатов.

2 голосов
/ 07 февраля 2010

Наилучшее соотношение производительности и беспорядка составляет 42.

Если говорить более серьезно, воспользуйтесь самым простым решением: получить все с помощью одного запроса. Не оптимизируйте, пока не столкнетесь с проблемой производительности. «Преждевременная оптимизация - корень зла»:)

0 голосов
/ 07 февраля 2010

«В настоящее время я пишу DAL на C # ...». В качестве дополнительного примечания вы можете проверить сообщение: Создание методов уровня доступа к данным из хранимых процедур. сэкономить много времени.

0 голосов
/ 07 февраля 2010

Я бы посмотрел на картину в целом - вам действительно нужно найти ингредиенты для 200 рецептов? Что происходит, когда у вас 2000?

Например, если это на веб-странице, я бы перечислил 200 рецептов (если не меньше из-за подкачки), и когда пользователь щелкнул один из них, чтобы увидеть ингредиент, я бы получил ингредиенты из базы данных.

Если это невозможно, у меня будет 1 сохраненный процесс, который возвращает один DataSet, содержащий 2 таблицы. Один с рецептами, а второй со списком ингредиентов.

0 голосов
/ 07 февраля 2010

Один сохраненный процесс, который возвращает 2 набора данных: «заголовок рецепта» и «детали рецепта»?

Это то, что я бы сделал, если бы мне нужны были данные сразу за один раз. Если мне это не понадобится сразу, я все равно получу 2 набора данных, но с меньшим количеством данных.

Нам показалось, что немного проще работать с этим в клиенте, чем с одним большим запросом, как предложил Андомар, но его / ее ответ по-прежнему очень актуален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...