我正在运行看起来像这样的查询
SELECT parent.field, child.field
FROM parent
JOIN child ON (child.id = parent.id
OR child.id = parent.otherid)
然而,这是非常慢的(大约100k记录,并且JOIN到实际版本中的其他表),但尽管尝试了索引
parent.id (PRIMARY),
parent.otherid,
child.id (PRIMARY),
and a composite index of parent.id and parent.otherid
在进行此连接时,我无法让MySQL使用任何这些索引。
我读到MySQL每个连接只能使用一个索引,但是当JOIN包含OR条件时,它是否可以在任何地方找到它是否可以使用复合索引。
有没有人知道是否可以使此查询引用索引? 如果是这样,怎么样?
我的解决方案
(很难让我回答下面的问题)
进行了大量调整,得出了一个相当不错的解决方案,它保留了加入和聚合其他表格的能力。
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
对于速度需要子查询中的条件来减少放置在临时表中的记录数,但是我在外部查询上有大量额外的连接,一些连接到子节点,一些连接到父节点(带有一些聚合)所以这个对我来说效果最好。
在很多情况下,联合会更快更有效,但由于我在父级上进行过滤,但是想要从子级(父级自引用)中获取额外的数据,因此联盟会为我创建额外的行,而我无法&# 39;巩固。 可以通过将父对象连接到自身并在外部查询中对where条件进行别名来找到相同的结果,但是这个对我很有效。
感谢Jirka对UNION ALL的建议,这是促使我到达这里的原因:)
答案 0 :(得分:7)
您的查询在理论上使得单个孩子有两个不同的父母,这将使其成为非常不标准的术语。但是,我们假设您的数据模式使其变得不可能。
然后,下面使用单独的索引给出相同的结果,每列一个索引。
SELECT parent.field, child.field
FROM parent
JOIN child ON child.id = parent.id
UNION ALL
SELECT parent.field, child.field
FROM parent
JOIN child ON child.id = parent.otherid
答案 1 :(得分:0)
EXPLAIN
SELECT parent.fld, child.fld
FROM parent JOIN child ON child.id = parent.id
UNION ALL
SELECT parent.fld, child.fld
FROM parent JOIN child ON child.id = parent.otherid
AND parent.otherid <> parent.id
使用MyISAM引擎的表:
id select_type TABLE TYPE possible_keys KEY key_len ref ROWS Extra
1 PRIMARY parent ALL PRIMARY 9999
1 PRIMARY child eq_ref PRIMARY PRIMARY 4 test.parent.id 1
2 UNION parent ALL parent_ix1 9999 USING WHERE
2 UNION child eq_ref PRIMARY PRIMARY 4 test.parent.otherid 1
UNION RESULT <union1,2> ALL
使用InnoDB引擎的表:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY child ALL PRIMARY 9903
1 PRIMARY parent eq_ref PRIMARY PRIMARY 4 test.child.id 1
2 UNION child ALL PRIMARY 9903
2 UNION parent ref parent_ix1 parent_ix1 5 test.child.id 1 Using where
UNION RESULT <union1,2> ALL