Накладные расходы для MySQL SELECTS - Лучше использовать Один или Несколько Последовательно

StackOverflow https://stackoverflow.com/questions/1852739

Вопрос

Есть ли заметная разница в производительности между наличием одного SELECT foo, bar, FROM users запрос, который возвращает 500 строк и 500 SELECT foo, bar, FROM users WHERE id = x запросы поступают все сразу?

В PHP-приложении, которое я пишу, я пытаюсь выбрать между написанием понятного, читаемого раздела кода, который произвел бы около 500 операторов SELECT;или написать его непонятным, сложным способом, который использовал бы только один SELECT, возвращающий 500 строк.

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

Справочная информация, на случай, если это актуально:1) Это модуль Drupal, закодированный на PHP 2) Рассматриваемые таблицы получают очень мало вставок и обновлений и редко блокируются 3) Соединения SQL невозможны по причинам, не имеющим отношения к вопросу

Спасибо!

Это было полезно?

Решение

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

Другие советы

Я бы не стал слишком беспокоиться о накладных расходах на подключение запросов mysql, особенно если вы не закрываете соединение между каждым запросом.Учтите, что если ваш запрос создает временную таблицу, вы уже потратили на выполнение запроса больше времени, чем потребовали накладные расходы на выполнение запроса.

Лично мне нравится выполнять сложные SQL-запросы, но я обнаружил, что размер таблиц, кэш запросов mysql и производительность запросов, которым необходимо выполнять проверку диапазона (даже по индексу), - все это имеет значение.

Я предлагаю это:

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

2) Закодируйте сложный запрос. Сравните результаты на предмет точности, а затем время.Затем используйте EXPECT в запросе, чтобы увидеть, какие строки были отсканированы.Я часто обнаруживал, что если у меня есть соединение, или ГДЕ x != y, или условие, которое создает временную таблицу, производительность запроса может сильно ухудшиться, особенно если я нахожусь в таблице, которая постоянно обновляется.Однако я также обнаружил, что сложный запрос может быть некорректным, а также что сложный запрос может быть более легко прерван по мере роста приложения.Сложные запросы обычно сканируют большие наборы строк, часто создавая временные таблицы и вызывая using where сканирует.Чем больше стол, тем дороже они получаются.Кроме того, у вас могут быть командные соображения, когда сложные запросы не соответствуют сильным сторонам вашей команды.

3) Поделитесь результатами со своей командой.

Сложные запросы с меньшей вероятностью попадут в кэш запросов mysql, и если они достаточно велики, не кэшируйте их.(Вы хотите сохранить кэш запросов mysql для часто выполняемых запросов.) Кроме того, запрос where с предикатами, которые должны сканировать индекс, также не подойдет.(x != y, x > y, x < y).Запросы, подобные SELECT foo, bar FROM users WHERE foo != 'g' and mumble < '360' в конечном итоге выполняется сканирование.(В этом случае затраты на выполнение запросов могут быть незначительными.)

Небольшие запросы часто можно выполнить без создания временных таблиц, просто получив все значения из индекса, при условии, что поля, которые вы выбираете и прогнозируете, проиндексированы.Таким образом, производительность запроса SELECT foo, bar FROM users WHERE id = x действительно здорово (особенно, если столбцы foo и bar индексируются как, иначе alter table users add index ix_a ( foo, bar );.)

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

Похоже, ты знаешь, что такое 500 id ценности есть, так почему бы не сделать что-то вроде этого:

// Assuming you have already validated that this array contains only integers
// so there is not risk of SQl injection

$ids = join(',' $arrayOfIds);

$sql = "SELECT `foo`, `bar` FROM `users` WHERE `id` IN ($ids)";
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top