【发布时间】:2014-12-30 10:55:59
【问题描述】:
当对具有 2 个值的 PRIMARY 键(使用 IN 或 OR 构造)执行 INNER JOIN 时,我在 EXPLAIN SELECT 中得到“检查每个记录的范围(索引映射:0x1)”
这里是查询:
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 吗?
-
嗯,我看到您只有主索引设置了 ID 号。尝试为 sender_id 和 receiver_id 添加索引,这可能有助于配对。
-
好吧,我做到了,它对 IN 结构没有帮助,但它适用于 OR 结构!我认为仅在正在搜索的列(user.id)上设置索引,而不是在(已经选择的)要测试的值来自(task.id_user)的列上。您能否发布一个实际答案(我将被允许接受)并向我(和其他人)解释为什么索引也应该设置在参考列上,而不仅仅是搜索的列?谢谢大卫!
-
等等,我说得太快了。它仍然不起作用。它只修复了我做的一个单一的用例:u.id = t.id_user OR u.id = t.id_user(这毫无意义但仍然导致问题并使查询更加简单)。很抱歉,它不起作用。还有什么想法吗?我确定我不是唯一一个尝试使用 OR 将一列与两列进行比较的人。我很惊讶我没有早点遇到。
-
嗨。你是什么意思,“它工作正常”?或“它不起作用”。此外,您实际上并没有说出您的期望。尽管你可能认为这很明显。请阅读minimal reproducible example 并采取行动。在这里,您没有示例输入、输出和所需的输出。 “我只解析了 1 行”是什么意思?并给出一个完整的例子(代码和数据)来展示你的问题。在给出您的规范时,还有什么其他 declarable 唯一和 FK 列集和非空列? PS“参考”和“搜索”列是什么意思?
标签: mysql sql indexing explain