Просмотр или хранимая процедура для сложных запросов? - PullRequest
12 голосов
/ 20 октября 2011

У меня несколько сложный запрос с несколькими (вложенными) подзапросами, которые я хочу сделать доступными для разработчиков приложений. Запрос является общим и генерирует представление с вычисленными значениями для набора наборов данных, и от разработчика ожидается, что ему потребуются только некоторые записи из того, что возвращает запрос (т. Е. Они ограничат результат для идентификатора какой-либо сущности, диапазона дат или некоторых например).

Я вижу 3 способа реализации этого:

  1. Позвольте разработчикам встраивать запрос в каждое приложение и добавлять свои собственные предложения WHERE по мере необходимости.
  2. Создайте хранимую процедуру, которая принимает в качестве параметров все условия, которые, как я ожидаю, понадобятся разработчикам (ради аргумента, скажем, я могу предсказать, что будет необходимо в обозримом будущем), и процедура выполнит сложный запрос и отфильтруйте его в соответствии с переданными параметрами.
  3. Реализуйте запрос в виде представления с несколькими вложенными представлениями (поскольку MySQL не разрешает вложенные запросы в представлениях), и пусть разработчики используют его в качестве таблицы и используют WHERE, чтобы каждое приложение применял нужные им фильтры. В настоящее время я смотрю на 3 дополнительных вложенных представления, в основном потому, что некоторые вложенные запросы используются несколько раз, а выполнение их в качестве вложенных представлений предотвращает дублирование - в противном случае это могло бы быть и хуже; -).

Что будет лучше по производительности? (при условии, что все индексации эквивалентны во всех случаях) Если хотите, используйте худшие сценарии.

что будет лучше с точки зрения обслуживания кода, как вы думаете?

Ответы [ 2 ]

7 голосов
/ 24 октября 2011

Мне нравятся вопросы, которые определяют «хорошо» - вы специально задали вопрос о производительности и удобстве обслуживания, что позволяет ответить на вопрос об этом компромиссе.

С точки зрения производительности, я недумаю, что между этими 3 вариантами может быть какая-то разница, если запросы и данные соответствуют ожидаемым сценариям.Я протестировал бы в 100 раз больше данных и, возможно, расширил бы предложение "where", чтобы увидеть, что происходит, но структура индексации и т. Д. С большей вероятностью повлияет на производительность, чем если бы вы выполняли тот же SQL из хранимого процесса черезили из клиентского приложения.

Лучший способ ответить на этот вопрос - проверить его - конечно, есть много конкретных деталей, которые могут лишить законной силы общее «Я ожидал бы x, y илиz "ответы, которые мы можем дать вам.Если производительность критична, воспользуйтесь инструментом заполнения базы данных (Redgate make, я использовал DBMonster в прошлом) и попробуйте все 3 варианта.

С точки зрения обслуживания, я бы сказал,вариант 4, который, на мой взгляд, является безусловно лучшим.

Вариант 4: создайте библиотеку доступа к данным, которая инкапсулирует доступ к вашим данным.Попросите библиотеку раскрыть методы и параметры, чтобы уточнить выбор записей.Попробуйте использовать шаблон спецификации (http://en.wikipedia.org/wiki/Specification_pattern). Используйте любые запросы, которые лучше всего подходят внутри библиотеки, и не беспокойте разработчиков подробностями реализации.

Если это не сработает - разнородный код приложения, слишком многоизменение для простого требования - я бы оценил параметры следующим образом:

  1. Встроенный SQL: в зависимости от количества повторного использования этого SQL, это может быть хорошо.есть только одна часть кода, которая выполняет SQL, она логически похожа на библиотеку доступа к данным. Если, однако, один и тот же фрагмент должен быть повторно использован во многих местах, это вероятный источник ошибок - небольшое изменение вSQL нужно будет повторять в нескольких местах.

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

  3. Просмотров: это, пожалуй, лучший выбор.Он размещает конкретную логику данных в одном месте, но способствует использованию логики на основе множеств, поскольку маршрут доступа осуществляется через оператор SELECT, а не путем выполнения процедурных операторов.Представления легко включить в другие запросы.

3 голосов
/ 24 октября 2011

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

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

Для решения manteinance я бы предпочел первое и второе решения, потому что вы можете вносить любые изменения в запрос, не делая никакихизменения базы данных.Если вы выберете 1-е решение, я бы обернул вызов запроса в функцию, чтобы у вас было только одно место для внесения изменений.

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

Что касается гибкости предложения where , вы можете добиться этого с помощью любого из предложенных решений.Вы можете добавить параметр where в свою функцию обертывания (1), вы можете добавить параметр where в хранимую процедуру, но будьте осторожны с инъекциями (2), или разработчик может добавить предложение where, как обычно, с представлением (3)

Учитывая, что в представлениях MySQL нет временных таблиц, , если запрос очень сложный , эти решения не будут наилучшими, если запрос используется многократно и по-разному (отключениеповышение производительности кеша). Я бы рассмотрел временную таблицу решение (таблица счетчиков), которая обновляет каждый период времени запрограммированной задачей / хроном (например, день, неделя, когда это необходимо) или обновляется путем установки триггеров пропппера.Это решение может немного улучшить производительность.

Надеюсь, это поможет, мне больше всего нравится решение View, но, возможно, его сложнее разработать с точки зрения базы данных.

...