我尝试使用多列匹配查询,以匹配从表A到表B的记录。但由于某种原因,查询运行速度非常慢。我尝试为连接表尝试不同的索引组合,但它们没有被使用,这就是为什么它总是进行全表扫描。
SELECT
nc.id, nc.firstName, nc.lastName,
nc.firmName, nc.location,
nc.city AS city, nc.state AS state,
ac.id, ac.lastName, ac.firstName, ac.middleName,
IFNULL(ac.suffixName, '') AS suffixName, ac.firmName, ac.city, ac.state
FROM
NormalContacts AS nc
JOIN
AllContacts AS ac ON ((nc.firstName = ac.firstName AND nc.lastName = fa.lastName) OR (nc.firstName = fa.middleName AND nc.lastName = ac.lastName))
AND (ac.city = nc.city AND ac.state = nc.state)
JOIN
FirmInputTable AS fit ON (fit.firmName = fa.firmName AND fit.otherFirmName = nc.firmName)
WHERE
nc.crdNumber IS NULL AND nc.city IS NOT NULL AND nc.state IS NOT NULL AND nc.firmName IS NOT NULL
NormalContacts
是1,000条记录,而AllContacts
是337,250条记录。 JOIN
条件中的所有字段都是varchar。
以下是EXPLAIN
结果:
AllContacts
中的* fa,抱歉输入错误。
希望任何人都可以建议一种方法来优化此查询或告诉我我做错了什么。提前谢谢!
答案 0 :(得分:1)
优化程序将查看索引和统计信息,以确定执行表的顺序。
在下文中,我将假设ON
仅说明表格彼此之间的关系,WHERE
仅用于过滤。
“第一”表可能(但不一定)是具有最具选择性WHERE
条件的表。因此,INDEX
需要关注WHERE
中的列。 (有时候GROUP BY
或ORDER BY
会发挥作用。)
JOIN
序列中的其他表将通过“嵌套循环连接”进入。这是“对于前一个表中的每一行,获取当前表中的行”。要执行此操作,它将使用与表相关的任何WHERE
子句以及ON
中提及此表的任何内容(可能还有以前的表)。因此,请考虑INDEX
和WHERE
条件下此表的ON
。
由于您无法始终预测优化程序将通过表格的顺序,因此最好添加索引以适应每个可能的顺序。
典型的快捷方式是WHERE
只提到一个表。该表几乎肯定会先被选中。
如果特定表格中有WHERE
/ ON
个引导,那么如何为特定表构建一个好的索引?见my cookbook
对于你的情况......
您似乎已正确拆分ONs
和WHEREs
- 好。
nc
似乎是WHERE
中提到的唯一表格,因此我们可以假设优化工具会从它开始。
IS NULL
与= constant
类似,但IS NOT NULL
就像一个范围,并非易于优化。我推荐
nc: INDEX(crdNumber, state)
(在这里,我猜测哪个nc
列最多/最不可能是NULL
。)
在nc
之后,只有ac
(又名fa
???)可能会来:
ON ((...) OR (...))
AND ac.city = nc...
AND ac.state = nc...
OR
通常无法进行索引或优化,因此我们留下了
ac: INDEX(city, state) -- in either order
lastName
可能会被OR
拉出(在修复ac / fa之后),从而导致
ac: INDEX(city, state, firstName) -- in any order
最后,fit
:
ON fit.firmName = ...
AND fit.otherFirmName = ...
导致
fit: INDEX(firmName, otherFirmName) -- in either order
请修复查询中的fa
;如果需要,我会修改我的答案。
注意:在这种情况下,INDEX(a,b)