как установить индексы для объединения и группировки по запросам - PullRequest
2 голосов
/ 05 апреля 2011

Допустим, у нас есть общее соединение, как показано ниже:

EXPLAIN SELECT *  
FROM visited_links vl
JOIN device_tracker dt ON ( dt.Client_id = vl.Client_id
AND dt.Device_id = vl.Device_id ) 
GROUP BY dt.id

если мы выполним объяснение, оно говорит:

id  select_type   table   type    possible_keys           key        key_len   ref                         rows   Extra
1   SIMPLE        vl      index   NULL                    vl_id      273       NULL                        1977   Using index; Using temporary; Using filesort
1   SIMPLE        dt      ref     Device_id,Device_id_2   Device_id  257       datumprotect.vl.device_id   4      Using where

Я знаю, что иногда трудно выбрать правильные индексы, когда вы используете group by, но какие индексы я мог бы установить, чтобы в этом запросе не использовалось «временное использование файловой сортировки»? почему это происходит? и особенно, почему это происходит после использования индекса?

Ответы [ 2 ]

2 голосов
/ 05 апреля 2011

Следует упомянуть, что поля, возвращаемые функцией select (в данном случае *), должны быть либо в предложении GROUP BY, либо использовать агрегатные функции, такие как SUM () или MAX (). В противном случае могут возникнуть неожиданные результаты. Это связано с тем, что если в базе данных не указано, как выбирать поля, не входящие в группу, по предложению, вы можете получить любого члена группы, в значительной степени наугад.


Я смотрю на это, разбивая запрос на части.

  1. у вас есть соединение (dt.Client_id = vl.Client_id и dt.Device_id = vl.Device_id), поэтому все эти поля должны быть проиндексированы в соответствующих таблицах.

  2. Вы используете GROUP BY dt.id, поэтому вам нужен индекс, который включает dt.id

НО ...

индекс для (dt.client_id, dt.device_id, dt.id) не будет работать для GROUP BY

и

индекс для (dt.id, dt.client_id, dt.device_id) не будет работать для объединения.

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

Смотрите также: http://ntsrikanth.blogspot.com/2007/11/sql-query-order-of-execution.html

0 голосов
/ 05 апреля 2011

Вы не опубликовали свои индексы, но прежде всего вам нужно иметь индекс для (client_id, device_id) для visited_links и (client_id, device_id, id) для device_tracker, чтобы убедиться, что запрос полностью проиндексирован.

Со страницы 191 превосходного Высокопроизводительного MySQL, 2-е изд. :

MySQL имеет два вида стратегий GROUP BY, когда он не может использовать индекс: он может использовать временную таблицу или файловую сортировку для выполнения группировки. Любой из них может быть более эффективным в зависимости от запроса. Вы можете заставить оптимизатор выбрать один или другой метод с помощью подсказок оптимизатора SQL_BIG_RESULT и SQL_SMALL_RESULT.

В вашем случае, я думаю, что проблема связана с объединением нескольких столбцов и использованием GROUP BY вместе, даже после того, как предложенные индексы введены в действие. Если вы удалите либо (a) одно из условий объединения, либо (b) GROUP BY, для этого не требуется сортировка файлов.

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

НТН!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...