2009-10-24 6 views
0

Я просто позволил медленный журнал (+ не с помощью индексов), и я получаю сотни записей для того же вида запроса (только user изменения)MySQL не использует индексы

SELECT id 
    , name 
    FROM `all` 
WHERE id NOT IN(SELECT id 
        FROM `picks` 
        WHERE user=999) 
ORDER BY name ASC; 

EXPLAIN дает:

+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 
| id | select_type  | table    | type | possible_keys | key | key_len | ref  | rows | Extra         | 
+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 
| 1 | PRIMARY   | all    | index | NULL    | name | 156  | NULL  | 209 | Using where; Using index; Using filesort | 
| 2 | DEPENDENT SUBQUERY | picks    | ref | user,user_2,pick | user_2 | 8  | const,func | 1 | Using where; Using index     | 
+----+--------------------+-------------------+-------+------------------+--------+---------+------------+------+------------------------------------------+ 

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

ответ

0

Я не обязательно согласен с тем, что «не в» и «существует» - это ВСЕГДА плохой выбор производительности, однако это может быть в этой ситуации.

Вы можете быть в состоянии получить свои результаты с помощью гораздо более простой запрос:

SELECT id 
    , name 
    FROM `all` 
    , 'picks' 
WHERE all.id = picks.id 
    AND picks.user <> 999 
ORDER BY name ASC; 
+0

Это получит все выборы, принадлежащие любому пользователю, кроме 999, правильно? Что делает запрос (но не эффективным образом), получает список «доступных» вариантов, но удаляет те, которые уже выбраны пользователем. –

+0

Этот запрос ничего не возвращает для строк, у которых нет соответствующей записи в 'picks', в то время как исходный запрос будет. –

+0

достаточно просто исправить, просто внешнее соединение. – northpole

0

«не в» и «существует» всегда плохой выбор производительности. Может быть, осталось присоединиться к чеканке «NULL», лучше попробовать.

0

Это, вероятно, лучший способ написать запрос. Задайте все параметры: all и попытайтесь найти подходящие строки от picks, которые разделяют те же самые id и user is 999. Если такой строки не существует, picks.id будет NULL, потому что он использует левое внешнее соединение. Затем вы можете отфильтровать результаты, чтобы возвращать только те строки.

SELECT all.id, all.name 
FROM 
    all 
    LEFT JOIN picks ON picks.id=all.id AND picks.user=999 
WHERE picks.id IS NULL 
ORDER BY all.name ASC 
Смежные вопросы