我有一个关系型MySQL数据库,几乎有4000条记录。联系人表与具有多对多关系的关键字表和备注表都相关。我编写了一个查询(使用PHP),它将检索每个联系人记录,并为每个联系人检索组连接函数中的所有相关备注和关键字。如果我只抓取联系人,查询执行得相对较快,但使用两个左连接和组连接,则需要近30秒。有办法加快速度吗?
这是我的查询:
SELECT c.*, GROUP_CONCAT(DISTINCT n.id, '[-]', n.value, '' SEPARATOR '---') as notes,
GROUP_CONCAT(DISTINCT kk.id, '[-]', kk.value) as keywords
FROM contacts c
LEFT JOIN notes n ON c.id LIKE n._contactID
LEFT JOIN
( SELECT k.*, kc._contactID as contactID
FROM keywords k
INNER JOIN keywords_contacts kc ON k.id LIKE kc._keywordID
) kk ON kk.contactID LIKE c.id
GROUP BY c.id
ORDER BY c.`Last Name`, c.`First Name`
在您的查询中,我可以看到c.id LIKE n._contactID
,这里LIKE使性能降低,因此使用=操作符并为外键字段_contactID
提供索引。
与k.id LIKE kc._keywordID
相同,使用=运算符代替LIKE,对_keywordID
字段应用索引
是的,用=
代替LIKE
;当您需要通配符时保留LIKE
,例如first_name LIKE 'H%'
。
更改为=
后,您可能仍然会发现查询速度很慢。考虑这些:
如果你不需要LEFT
,就不要使用它。通常情况下,从作为子查询的'table'开始会更快(参见LEFT JOIN ( SELECT ...)
),但使用LEFT
往往会抑制这种情况。
如果GROUP BY
和ORDER BY
是相同的,你可以避免临时表和排序:
GROUP BY c.`Last Name`, c.`First Name`, c.id
ORDER BY c.`Last Name`, c.`First Name`, c.id
请提供SHOW CREATE TABLE
和EXPLAIN SELECT ...
,以便我们对索引进行评审。