У меня есть следующие два запроса (*)
, которые отличаются только в поле, которое ограничено в предложении WHERE
(name1
vs name2
):
SELECT A.third_id, COUNT(DISTINCT B.fourth_id) AS num
FROM first A
JOIN second B ON A.third_id = B.third_id
WHERE A.name1 LIKE 'term%'
SELECT A.third_id, COUNT(DISTINCT B.fourth_id) AS num
FROM first A
JOIN second B ON A.third_id = B.third_id
WHERE A.name2 LIKE 'term%'
Оба поля name
имеют на них индекс с одним столбцом. Также есть индекс как для столбцов third_id
так и для fourth_id
(которые являются внешними ключами в других таблицах, но здесь это не актуально).
Согласно EXPLAIN
, первый ведет себя так: это то, что я хочу:
+----+-------------+-------+-------+---------------+----------+---------+---------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+----------+---------+---------------+------+-------------+
| 1 | SIMPLE | A | range | third_id,name | name | 767 | NULL | 3491 | Using where |
| 1 | SIMPLE | B | ref | third_id | third_id | 4 | db.A.third_id | 16 | |
+----+-------------+-------+-------+---------------+----------+---------+---------------+------+-------------+
Второй делает это, чего я определенно не хочу:
+----+-------------+-------+------+----------------+----------+---------+---------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+----------------+----------+---------+---------------+--------+-------------+
| 1 | SIMPLE | B | ALL | third_id | NULL | NULL | NULL | 507539 | |
| 1 | SIMPLE | A | ref | third_id,name2 | third_id | 4 | db.B.third_id | 1 | Using where |
+----+-------------+-------+------+----------------+----------+---------+---------------+--------+-------------+
Что, черт возьми, происходит здесь? Как заставить второго вести себя правильно (т.е. Как первый)?
(*)
Собственно, я этого не делаю. У меня несколько более сложные запросы; Я удалил дополнительные задания для этого сообщения и перепрофилировал их на минимальные запросы, которые по-прежнему демонстрируют проблемное поведение. Кроме того, имена были изменены для защиты виновных.
Добавьте инструкции CREATE TABLE к вашему сообщению. Также будет полезен реальный оператор SELECT.
1 возможная причина заключается в том, что имя2 имеет гораздо больший процент значений, начиная с "term%".
Попробуйте выполнить порядок таблиц в запросе с помощью STRAIGHT_JOIN.
SELECT A.third_id, COUNT(DISTINCT B.fourth_id) AS num
FROM first A
STRAIGHT_JOIN second B ON A.third_id = B.third_id
WHERE A.name2 LIKE 'term%'
Сколько записей в этих таблицах? Проверьте мощность/избирательность в столбце name2.
Если селективность низкая, попробуйте Naktibalda "STRAIGHT_JOIN" или подсказки http://dev.mysql.com/doc/refman/5.0/en/index-hints.html