【发布时间】:2012-06-20 21:17:18
【问题描述】:
我正在运行一个看起来像这样的查询
SELECT parent.field, child.field
FROM parent
JOIN child ON (child.id = parent.id
OR child.id = parent.otherid)
然而,这确实很慢(大约 100k 条记录,并且在真实版本中连接到其他表),但尽管尝试了索引
parent.id (PRIMARY),
parent.otherid,
child.id (PRIMARY),
and a composite index of parent.id and parent.otherid
在进行此连接时,我无法让 MySQL 使用任何这些索引。
我读到 MySQL 每个连接只能使用一个索引,但是当 JOIN 包含 OR 条件时,它是否可以使用复合索引却找不到任何地方。
这里有人知道是否可以让这个查询引用索引吗? 如果有,怎么做?
我的解决方案
(所以不会让我在 atm 下面回答我自己的问题)
经过一系列调整,提出了一个相当不错的解决方案,它保留了 JOIN 和聚合其他表的能力。
SELECT parent.field, child.field
FROM parent
JOIN (
SELECT parent.id as parentid,
# Prevents the need to union
IF(NOT ISNULL(parent.otherid) AND parent.otherid <> parent.id,
parent.otherid,
parent.id) as getdataforid
FROM parent
WHERE (condition)
) as foundrecords
ON foundrecords.parentid = parent.id
JOIN child ON child.id = parent.getdataforid
为了提高速度,需要子查询内部的条件来减少放置在临时表中的记录数,但我在外部查询上有大量额外的连接,一些连接到子查询,一些连接到父查询(有一些聚合)所以这个最适合我。
在许多情况下,联合会更快、更有效,但由于我正在过滤父级,但想要来自子级的额外数据(父级自我引用),联合导致我无法合并的额外行. 只需将 parent 连接到自身并在外部查询中为 where 条件设置别名,就有可能找到相同的结果,但这对我来说非常有效。
感谢 Jirka 的 UNION ALL 建议,这是促使我来到这里的原因 :)
【问题讨论】:
-
您是否对查询运行了
explain select ...? -
是的,解释是什么让我知道它没有使用任何索引进行此连接。