Mysql select с в предложении не использует индекс - PullRequest
4 голосов
/ 23 декабря 2011

У меня есть таблица контактов, у которой есть первичный ключ id.Он также имеет вторичный индекс idx_id_del_user (id, удаленный, user_id).

В следующем запросе используется индекс, и поэтому он очень быстрый -

select id
from jts_contacts
where id = '00000402-25c8-7375-e3df-4ec5b66de11d'
and deleted = 0;

1 строка, выбранная за 0,0098 с

Однако, когда я использую предложение in, внешний запрос переходит в полное сканирование таблицы.Я ожидаю, что он будет использовать либо первичный ключ, либо idx_id_del_user.

select  *
from jts_contacts FORCE INDEX (idx_id_del_user)
where id in
(select id
from jts_contacts
where id = '00000402-25c8-7375-e3df-4ec5b66de11d')
and deleted = 0

1 строка, выбранная за 9 с

Объяснить план -

id, select_type,          table,         type, possible_keys,                 key, key_len, ref, rows, Extra
------------------------------------------------------------------------------------
1, 'PRIMARY',            'jts_contacts', 'ALL', '',                           '',   '',     '', 1127275, 'Using where'
2, 'DEPENDENT SUBQUERY', 'jts_contacts', 'const', 'PRIMARY,idx_id_del_user', 'PRIMARY', '108', 'const', 1, 'Using index'

В этой таблице 1,2миллион записей и таблица была проанализирована.Я пробовал без параметра FORCE INDEX, но он по-прежнему не использует индекс.Любые предложения по ускорению этого запроса?


Предостережение: использование объединения вместо предложения in будет работать, однако, поскольку это сгенерированный запрос из существующего продукта - его нельзя изменить для использования объединений.

Ответы [ 2 ]

2 голосов
/ 23 декабря 2011

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

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

0 голосов
/ 08 февраля 2013

У меня только что возникла та же проблема, и после прочтения поста Маркуса Адамса я подумал о том, что я узнал из запуска UPDATE для таблицы на основе данных из этой же таблицы: создать производную таблицу сначала вот так:

SELECT * FROM jts_contacts WHERE id IN
(SELECT id FROM
    (SELECT id FROM jts_contacts WHERE id = '00000402-25c8-7375-e3df-4ec5b66de11d')
temp)
AND deleted = 0

Сначала будет извлечен полный результат из внутреннего запроса в производную таблицу temp, а затем будет выполнен внешний запрос на основе этого.

Этот шаблон увеличил скорость моих похожих запросов с минут до менее секунды. Я не шучу.

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