Объединение - это многотабличный запрос, выполняемый относительно таблиц, объ­единенных посредством одного общего поля или большего количества полей. К запросам такого типа часто прибегают для лучшего использования взаимосвязей между нормиро­ванными таблицами СУБД. Кроме того, запросы такого типа предоставляют программистам SQL возможность связать записи из отдельных таблиц.
Подзапрос - это оператор SELECT, находящийся внутри другого оператора SELECT. Подзапрос часто используется для разбиения сложного запроса на последовательные ло­гические шаги или для использования в запросе результатов другого запроса. В результате вместо двух (или более) запросов выполняется один запрос, содержащий один (или больше) подзапрос.
В MySQL лучше оптимизировать объединения, чем подзапросы, а поэтому, если вы обнаружите, что средняя нагрузка на MySQL сервер достигает неприемлемо высокого уровня, просмотрите код своей программы и попробуйте заменить подзапросы объединениями и последовательностями объединений. Например, несмотря на то, что следующий подзапрос определенно допустим,
Оптимизация многотабличных запросов
следующее эквивалентное объединение будет работать быстрее (обратите внимание на время выполнения) благодаря алгоритмам оптимизации MySQL.
Оптимизация многотабличных запросов
Также вполне заслуживает внимания хорошая идея согласовывать объединяемые поля как по типу, так и по длине. MySQL несколько менее эффективен при использовании индексов на объединенных полях разной длины и/или типа.
Также вы можете превратить неэффективные подзапросы в более эффективные объе­динения путем использования обобщенных функций и модификаторов MySQL. Рассмотрим следующий подзапрос.
Оптимизация многотабличных запросов
Оптимизация многотабличных запросов
Сеансовые переменные также могут пригодиться, если вы не хотите работать с вло­женными подзапросами. Следующий запрос поможет выявить всех клиентов, суммы счет-фактур которых всегда превышали средние показатели.
Оптимизация многотабличных запросов
Использование временных таблиц
MySQL позволяет создавать временные таблицы с помощью команды CREATE TEMPORARY TABLE. Эти таблицы называются так потому, что они существуют только во время одного сеанса MySQL и автоматически удаляются, когда вызвавший их клиент завершает соединение с сервером. Эти таблицы удобны для временного хранения сеансовых данных и для вычислений. А так как они существуют только для определенного сеанса, два разных сеанса могут использовать одноименные временные таблицы, не вызывая при этом конфликтов.
Так как временные таблицы хранятся в памяти, они обрабатываются значительно быстрее тех, что хранятся на дисках. Следовательно, они могут эффективно использоваться в качестве промежуточной области хранения данных для ускорения выполнения запросов, помогая разбить сложные запросы на простые составляющие, или как поддержка подзапросов и объединений.
Например, допустим, у вас есть сложный запрос, который выбирает множество разных значений из определенного поля, а процессор MySQL неспособен оптимизировать ваш запрос из-за его сложности. Находчивые SQL-программисты могут увеличить производительность, разбив один сложный запрос на множество простых (которые лучше поддаются оптимизации), а затем, создав временную таблицу с ключом UNIQUE в соответствующем поле, использовать команды INSERT IGNORE...SELECT для сохранения полученных результатов в ней. Результат: множество разных значений этого поля и, возможно, более быстрое выполнение запроса.
Вот еще один пример: допустим, у вас имеется таблица, содержащая информацию о месячной стоимости транзакций, скажем, в 300 тыс. записей. В конце каждого дня ваше приложение должно сгенерировать отчет по транзакциям, произведенным в течение дня. В такой ситуации, с точки зрения производительности, неразумно ежедневно запускать для всех 300 тыс. записей функции SUM() и AVG(). Более эффективным решением было бы поместить во временную таблицу только транзакции за текущий день с помощью операторов INSERT...SELECT, запустить суммирующие функции для этой таблицы, чтобы сгенерировать отчет, а затем временную таблицу удалить. Так как временная таблица содержала бы меньшее подмножество записей, производительность была бы выше, а, нагрузка на сервер соответственно, меньше.