Оптимизация запросов в MySQL MostInfo.net (http://mostinfo.net/article/12/92.htm) Повышаем быстродействие своих скриптов |
||||
Соколов Сергей phpclub.ru 08-10-2004 |
||||
Оптимизация – это изменение системы с целью повышения ее
быстродействия.
Рассмотрим подробнее оптимизацию запросов. Оптимизация запросов - наиболее простой и приводящий к наиболее высоким результатам тип оптимизации. SELECT Запросами, которые чаще всего поддаются оптимизации, являются запросы на выборку. Для того чтобы посмотреть как будет выполняться запрос на
выборку используется оператор EXPLAIN: Основная ошибка начинающих - это отсутствие индексов на
нужных полях или создание оных на ненужных полях. Если вы
делаете простую выборку наподобие: Если вы используете соединение 2 или более таблиц:
Или в более общем виде: То вам следует создать индексы по полям, по которым будут присоединятся таблицы. В данном случае это поля b.id и c.id. Однако это утверждение верно только в том случае, если выборка будет происходить в том порядке, в котором они перечислены в запросе. Если, к примеру, оптимизатор MySQL будет выбирать записи из таблиц в следующем порядке: c,b,a, то нужно будет проставить индексы по полям: b.c_id и a.b_id. При связывании с помощью LEFT JOIN таблица, которая идет в запросе слева, всегда будет просматриваться первой. Про синтаксис создания индексов можно прочитать в
документации: Более подробно про использовании индексов можно прочитать
здесь: Иногда бывает такая ситуация, что нам постоянно приходится
делать выборки из одной и той же части некоторой очень большой
таблицы, например, во многих запросах происходит соединение с
частью таблицы: В таких случаях может быть разумным вынести эту часть в
отдельную временную таблицу: Также если мы несколько раз рассчитываем агрегатную функцию для одних и тех же данных, то для ускорения следует сделать такой расчет отдельно и положить его результат во временную таблицу. Также бывают тормоза, когда люди пытаются в одном запросе «поймать сразу 2-х зайцев», например, на форуме phpclub’а автор следующего запроса спрашивал, почему он тормозит:
Автор запроса пытается в одном запросе посчитать максимальное значение атрибута из одной таблицы и кол-во записей в другой таблице. В результате к запросу приходится присоединять 2 разные таблицы, которые сильно замедляют выборку. Для увеличения быстродействия такой выборки необходимо вынести подсчет MAX’а или COUNT’а в отдельный запрос. Для подсчета кол-ва строк используйте функцию COUNT(*), c указанием "звездочки" в качестве аргумента. Почему COUNT(*) обычно быстрее COUNT(id), поясню на примере: Есть таблица message: id | user_id | text Нам надо подсчитать сообщения пользователя с заданым $user_id Сравним 2 запроса:
и
Для выполнения первого запроса нам достаточно просто пробежаться по индексу user_id и подсчитать кол-во записей, удовлетворяющих условию - такая операция достаточно быстрая, т.к., во-первых, индексы у нас упорядочены и ,во-вторых, часто находятся в буфере. Для выполнения второго запроса мы сначала проходим по индексу, для отбора записей удовлетворяющих условию, после чего если запись попадает под условие, то вытаскиваем ее (запись скорее всего будет на диске) чтобы получить значение id и только потом инкриментим счетчик. В итоге получаем, что при большом кол-ве записей скорость первого запроса будет выше в разы. UPDATE, INSERT Скорость вставок и обновлений в базе зависит от размера
вставляемой (обновляемой) записи и от времени вставки
индексов. Время вставки индексов в свою очередь зависит от
количества вставляемых индексов и размера таблицы. Эту
зависимость можно выразить формулой: При частом изменении некоторой большой таблицы с большим количеством индексов имеет смысл производить вставки в другую небольшую вспомогательную таблицу с тем же набором полей (но с отсутствием индексов) и периодически перекидывать данные из нее в основную таблицу, очищая вспомогательную. При этом следует учесть, что данные будут выводиться с запозданием, что не всегда может быть возможным. «Чтобы удалить все строки в таблице, нужно использовать команду TRUNCATE TABLE table_name.» © документация MySQL. Ответы на многие вопросы по оптимизации запросов можно найти в мануале: http://www.mysql.com/doc/ru/Query_Speed.html Оригинал статьи находится по адресу http://mostinfo.net/article/12/92.htm | ||||