2015-09-30 2 views
0

У меня есть 2 запроса, которые делают то же самое и дают один и тот же набор результатов, но пишут по-другому. Рассматривая их профиль, они занимают почти одно и то же время: около 0.075 секундMySQL: «Отправка данных» против «Копирование в таблицу tmp»

Увлекательно то, что запрос № 1 занимает почти все время выполнения процесса в состоянии «Копирование в таблицу tmp». Поскольку запрос №2 занимает почти все время выполнения процесса в состоянии «Отправка данных».

Итак, мой вопрос:

Какое состояние лучше для запроса MySQL к отработавшим все свое время, «Передача данных» или «Копирование на TMP таблицу»?

запроса # 1 (проводит время выполнения в состоянии "Копирование в TMP таблицу")

SELECT ac.album_category_id, ac.name, ac2.album_category_id, ac2.name, ac2.description, t2.total 
FROM album_category ac 
JOIN album_category ac2 ON ac2.parent_album_category_id = ac.album_category_id 
JOIN (
    SELECT a.album_category_id cat_id, SUM(result.count_image) total 
    FROM album a 
    JOIN (
     SELECT IFNULL(a.parent_album_id, a.album_id) p_album_id, COUNT(ai.image_id) count_image 
     FROM album_image ai 
     JOIN album a ON a.album_id = ai.album_id 
     JOIN image i ON i.image_id = ai.image_id 
     WHERE i.is_listed = 1 
     GROUP BY p_album_id 
    ) result ON result.p_album_id = a.album_id 
    GROUP BY a.album_category_id 
) t2 ON t2.cat_id = ac2.album_category_id 
ORDER BY ac.position, ac2.position 

запрос # 2 (проводит время выполнения в состоянии "Передача данных")

SELECT ac.album_category_id, ac.name, ac2.album_category_id, ac2.name, ac2.description, t3.total 
FROM album_category ac 
JOIN album_category ac2 ON ac2.parent_album_category_id = ac.album_category_id 
JOIN (
    SELECT a2.album_category_id cat_id, SUM(t2.sum_image) total 
    FROM album a2 
    JOIN (
     SELECT IFNULL(a.parent_album_id, a.album_id) p_album_id, SUM(t1.count_image) sum_image 
     FROM album a 
     JOIN (
      SELECT ai.album_id album_id, COUNT(ai.image_id) count_image 
      FROM album_image ai 
      JOIN image i ON i.image_id = ai.image_id 
      WHERE i.is_listed = 1 
      GROUP BY ai.album_id 
     ) t1 ON t1.album_id = a.album_id 
     GROUP BY p_album_id 
    ) t2 ON t2.p_album_id = a2.album_id 
    GROUP BY a2.album_category_id 
) t3 ON t3.cat_id = ac2.album_category_id 
ORDER BY ac.position, ac2.position 

EDIT

Согласно запросу jkavalik, я добавил EXPLAIN. Я не уверен, как добавить его в текст, поэтому вместо этого я добавил изображения. Надеюсь, все в порядке.

EXPLAIN для запроса # 1

enter image description here

EXPLAIN для запроса # 2 enter image description here

+0

Чтобы узнать, что вам нужно проверить план выполнения запроса с помощью [EXPLAIN] (https://dev.mysql.com/doc /refman/5.5/en/using-explain.html).Пожалуйста, добавьте планы на эти два вопроса к вопросу. – jkavalik

+0

ok, я отредактировал вопрос и добавил EXPLAIN – Marco

ответ

0

Копирование на TMP таблицу: Сервер копирования во временную таблицу в памяти.

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

http://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html

Передача данных будет происходить на большинстве запросов, но состояние запроса будет меняться так быстро на быстрых запросов, которые вы даже не заметите его. Однако, поскольку вы замечаете это, в то время может быть много ИО. Когда вы запускаете этот запрос, в окне терминала также смотрите iostat -x 10 и наблюдайте за ожиданием ввода-вывода на диск (при условии, что вы используете Linux/Unix). Если ожидание подтягивается, MySQL читает с диска, выполняет свою работу, а затем готов к передаче данных клиенту.

Копирование в таблицу tmp означает, что результат части запроса или подзапроса перемещается в память, чтобы можно было выполнить больше работы с использованием этих временных данных (temp table). Всякий раз, когда я сталкивался с этим состоянием, есть возможность оптимизации. Я бы больше беспокоился об обоих состояниях, если запрос занимает несколько секунд, чтобы вернуться. Я бы оптимизировал запрос 1 в вашем случае. Вы можете попробовать увеличить innodb_buffer_pool_size (если вы используете InnoDB двигатель)

https://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html

Смежные вопросы