Существуют ситуации, которые требуют, чтобы действительно большой запрос соединял несколько таблиц вместе с операторами выбора в них для получения желаемых результатов.
Мой вопрос заключается в том, следует ли нам рассмотреть возможность использования нескольких небольших запросов и перенести логические операции на уровень приложений, выполняя запросы к БД более чем за один вызов, или лучше иметь их все за один раз?
Например, рассмотрим следующий запрос:
SELECT *
FROM `users`
WHERE `user_id` IN (SELECT f2.`friend_user_id`
FROM `friends` AS f1
INNER JOIN `friends` AS f2
ON f1.`friend_user_id` = f2.`user_id`
WHERE f2.`is_page` = 0
AND f1.`user_id` = "%1$d"
AND f2.`friend_user_id` != "%1$d"
AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
FROM `friends`
WHERE `user_id` = "%1$d"))
AND `user_id` NOT IN (SELECT `user_id`
FROM `friend_requests`
WHERE `friend_user_id` = "%1$d")
AND `user_image` IS NOT NULL
ORDER BY RAND()
LIMIT %2$d
Какой лучший способ сделать это?
источник
Как человек, который должен поддерживать / очищать эти большие и сложные запросы, я бы сказал, что гораздо лучше разбить их на несколько небольших, легко понимаемых кусков. Это не обязательно лучше с точки зрения производительности, но вы, по крайней мере, даете SQL больше шансов придумать хороший план запросов.
Облегчите жизнь людям, которые следуют за вами, и они будут говорить о вас хорошие слова. Сделай им тяжело, и они тебя проклянут.
источник
Мои 2 цента на запросе 2 ключевых слов производительности и масштабируемости:
Производительность запросов. Параллелизм SQL Server уже делает очень хорошую работу, разбивая запросы на многопоточные поиски, поэтому я не уверен, какое улучшение производительности запросов вы увидите, выполнив его для SQL Server. Вам нужно будет взглянуть на план выполнения, чтобы увидеть степень параллелизма, которую вы получите при его выполнении, и сравнить результаты в обоих направлениях. Если вам в конечном итоге придется использовать подсказку для запроса, чтобы получить такую же или лучшую производительность, то IMO того не стоит, так как подсказка для запроса может оказаться неоптимальной позже.
Масштабируемость: чтение запросов может быть проще, как указано в модуле данных, и разбивка его на отдельные запросы имеет смысл, если вы можете использовать свои новые запросы и в других областях, но если вы не собираетесь использовать их и для других вызовов, тогда это будет еще больше хранимых процедур для управления одной задачей, и IMO не будет способствовать масштабируемости.
источник
LIMIT
Иногда нет другого выбора, кроме как разбить большой / сложный запрос на маленькие. Лучший способ определить это - использовать
EXPLAIN
оператор сSELECT
оператором. Число трассировок / сканирований, которые ваша база данных собирается выполнить для получения ваших данных, является произведением значений «строк», возвращаемых вашимEXPLAIN
запросом. В нашем случае у нас был запрос, объединяющий 10 таблиц. Для конкретной записи, след составил 409 млн., Что привело к ведению блога нашей БД и увеличило загрузку ЦП нашего сервера БД более чем на 300%. Мы смогли получить ту же информацию, разделив запросы намного быстрее.Итак, короче говоря, в некоторых случаях разделение сложного / большого запроса имеет смысл, но в других это может привести ко многим проблемам с производительностью или обслуживаемостью, и это следует рассматривать в каждом конкретном случае.
источник