2009-05-14 4 views
24

Один из моих запросов в MySQL 5.0.45 работает медленно в фазе «отправки данных». Запрос представляет собой простой выбор, возвращает около 300 целых идентификационных полей в качестве набора результатов.MySql - медленная фаза отправки данных

 
mysql> SELECT source_id FROM directions WHERE (destination_id = 10); 
+-----------+ 
| source_id | 
+-----------+ 
|   2 | 
|   8 | 
... 
|  2563 | 
+-----------+ 
341 rows in set (2.13 sec) 

Я не сомневаюсь, почему фаза «отправки данных» настолько медленная и что можно сделать, чтобы сделать ее быстрой. Обратите внимание: я выполняю этот запрос в приглашении MySQL на самом сервере, поэтому не ожидаю, что он потратит так много времени на «отправку данных». Любые подсказки?

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

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

Профилирование результат:

 
mysql> show profile for query 4; 
+--------------------------------+----------+ 
| Status       | Duration | 
+--------------------------------+----------+ 
| (initialization)    | 0.000003 | 
| checking query cache for query | 0.000051 | 
| checking permissions   | 0.000007 | 
| Opening tables     | 0.000011 | 
| System lock     | 0.000005 | 
| Table lock      | 0.000023 | 
| init       | 0.00002 | 
| optimizing      | 0.00001 | 
| statistics      | 0.00006 | 
| preparing      | 0.000014 | 
| executing      | 0.000005 | 
| Sending data     | 2.127019 | 
| end       | 0.000015 | 
| query end      | 0.000004 | 
| storing result in query cache | 0.000039 | 
| freeing items     | 0.000011 | 
| closing tables     | 0.000007 | 
| logging slow query    | 0.000047 | 
+--------------------------------+----------+ 
18 rows in set (0.00 sec) 

UPDATE: Я наткнулся на следующий URL, который говорит

 
Each time means the time elapsed between the previous event and the new event. So, the line: 
| Sending data | 0.00016800 | 
means that 0.00016800 seconds elapsed between "executing" and "Sending data". It is, it takes 0.00016800 seconds to execute the query. 

http://forums.mysql.com/read.php?24,241461,242012#msg-242012

Может кто-нибудь проверить?

+7

Это утверждение не соответствует действительности на связанной странице. Если вы выполняете 'SHOW PROCESSLIST' во время выполнения запроса, он покажет, что запрос действительно находится в состоянии ** Sending data **. (Не в предыдущем). - И, пожалуйста, никто не скажет, что processlist показывает * следующий шаг в выполнении. :) – vbence

+0

@vbence: вы когда-нибудь видели запрос, который требует больше, чем несколько человек для запуска? Указанная теория имеет смысл. –

+0

@ user9111337 О да. Совокупные операторы (GROUP BY) с WHERE caluse обычно приводят к выборам, которые не могут быть решены с помощью индекса (EXPLAIN ... скажет «ИСПОЛЬЗОВАНИЕ ГДЕ») - если таблица достаточно большая, это может занять несколько минут. - Как это сообщается? Вы можете увидеть это сами, попробовав 'SHOW PROCESSLIST'. – vbence

ответ

1

У вас есть индексы на этом столе? Вы сказали, что он возвращает около 300. Но сколько нужно искать, чтобы найти эти 300?

15

Обычно объяснение-план - лучшее место для начала, когда у вас медленный запрос. Чтобы получить один, запустите

DESCRIBE SELECT source_id FROM directions WHERE (destination_id = 10); 

Это покажет вам таблицу с указанием шагов, необходимых для выполнения вашего запроса. Если вы видите большое значение в столбце «rows» и NULL в столбце «key», это означает, что ваш запрос должен проверять большое количество строк, чтобы определить, какие из них нужно вернуть.

В этом случае добавление индекса по адресу destination_id должно значительно ускорить ваш запрос, с некоторыми затратами на вставку и удаление скорости (так как индекс также необходимо будет обновить).

+10

Хотя я согласен с тем, что запрос EXPLAIN/DESCRIBE - это способ найти как это исправить, вы на самом деле не описали фазу «отправки данных». См. Http://dev.mysql.com/doc/refman/5.0/en/general-thread-states.html –

-2

Ваш запрос проводит 2.127019 по , выполнив запрос. Вероятно, это потому, что у вас большой объем данных, и у вас отсутствует индекс в столбце destination_id. Попробуйте:

CREATE INDEX index_destination_id НА направлениях (destination_id);

Тогда ваш запрос будет работать гладко.

+3

Это утверждение FALSE см. Мой комментарий к вопросу. – vbence

+0

Но для меня, в другом сценарии, на самом деле добавление индекса разрешило мой медленный запрос - иногда очевидное пропускается. –

6

Возможно, вы можете посмотреть аппаратную часть сервера mysql. Как Mysql doc говорит:

Передача данные

Нить чтение и строка обработки для ЗЕЬЕСТА и отправки данных клиента. Поскольку операции, происходящие во время этого состояния, имеют тенденцию выполнять большие объемы доступа к диску (чтение), это часто самое продолжительное состояние в течение всего времени существования данного запроса.

Так что, если ваш сервер имеет медленный диск I/O из-за огромного дб/файла таблицы или отключенной опции tableperfile InnoDB/фрагментация неправильно настроен процесс аварии/RAID/диск начал (ждать в ближайшее время диск смерти)/любой другой причина замедления дискового ввода-вывода - это может быть причиной резкого увеличения «Отправки данных», так как на этом этапе сервер собирает все запрошенные данные с диска и отправляет его клиенту.

Конечно, вы должны попытаться оптимизировать выбор, чтобы сначала использовать индексы и убедиться, что это не проблема программирования, так как это в большинстве случаев влияет на это время этапа.

0

У меня был тот же вопрос: Отправить данные очень медленно, но у меня были правильные индексы и т.д.

После долгих копаться, я обнаружил, что мой join сравнивал два поля, которые были проиндексированы, но имели разные Сортировка - одна была latin1_swedish_ci, а другая - uft8_general_ci.

После того, как я послал их обоих utf8 запрос значительно быстрее было (от 2,7 секунды до 0,002 секунды)

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