Я получаю «Диапазон проверен для каждой записи (индексная карта: 0x1)» в EXPLAIN SELECT при выполнении ВНУТРЕННЕГО СОЕДИНЕНИЯ для ПЕРВИЧНОГО ключа с двумя значениями (с использованием конструкций IN или OR)
Вот запрос:
SELECT *
FROM message AS m
INNER JOIN user AS u
ON u.id = m.sender_id OR u.id = m.receiver_id
Когда я делаю объяснение, это дает мне:
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------------------------+
| 1 | SIMPLE | u | ALL | PRIMARY | null | null | null | 75000 | Range checked for each record (index map: 0x1)|
+----+-------------+-------+------+---------------+------+---------+------+-------+-----------------------------------------------+
Не может быть...
Если я попробую это, я получу тот же результат:
SELECT *
FROM message AS m
INNER JOIN user AS u
ON u.id IN(m.sender_id, m.receiver_id)
Но если я сделаю это, все будет работать нормально, и я проанализирую только 1 строку:
SELECT *
FROM message AS m
INNER JOIN user AS u
ON u.id = m.sender_id
Как это возможно? Я присоединяюсь к первичному ключу со значениями того же типа. (фактический запрос «немного» сложнее, но ничего особенного, 2 внутренних соединения и, наконец, одно левое соединение)
Должно быть 2 строки, точка.
Спасибо за любой вклад в это (провел некоторое исследование, но не нашел ничего ценного, кроме «пожалуйста, добавьте индекс», который, очевидно, здесь не применим)
РЕДАКТИРОВАТЬ: да, я попробовал оператор USE INDEX, но все равно не повезло
РЕДАКТИРОВАТЬ: Вот очень простая схема для воспроизведения этого странного поведения MySQL:
CREATE TABLE test_user (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(30),
PRIMARY KEY (id)
);
CREATE TABLE test_message (
id INT NOT NULL AUTO_INCREMENT,
sender_id INT NOT NULL,
receiver_id INT NOT NULL,
PRIMARY KEY (id),
INDEX idx_sender (sender_id),
INDEX idx_receiver (receiver_id)
);
EXPLAIN SELECT *
FROM test_message AS m
INNER JOIN test_user AS u
ON u.id = m.sender_id OR u.id = m.receiver_id;
FULL OUTER JOIN
. А в SQL нет такого понятия, какFULL INNER JOIN
. - person Bill Karwin   schedule 03.11.2017EXPLAIN
-- В запросе упоминаются две таблицы;EXPLAIN
упоминает только один. Пожалуйста исправьте. - person Rick James   schedule 06.11.2017