【发布时间】:2010-09-16 05:02:50
【问题描述】:
我一直在分析我正在处理的应用程序中的一些查询,我遇到了一个查询,它检索的行数超过了必要的行数,结果集在应用程序代码中被缩减。
将 LEFT JOIN 更改为 INNER JOIN 会将结果集修剪为所需的内容,并且可能还会提高性能(因为选择的行更少)。实际上,LEFT JOIN'ed 查询的性能优于 INNER JOIN'ed,只需一半的时间即可完成。
LEFT JOIN:(总共 127 行,查询耗时 0.0011 秒)
INNER JOIN:(总共 10 行,查询耗时 0.0024 秒)
(我多次运行查询,这些都是平均值)。
在两者上运行 EXPLAIN 无法解释性能差异:
对于 INNER JOIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1 Using where
对于左连接:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE contacts index NULL name 302 NULL 235 Using where
1 SIMPLE lists eq_ref PRIMARY PRIMARY 4 contacts.list_id 1
1 SIMPLE lists_to_users eq_ref PRIMARY PRIMARY 8 lists.id,const 1
1 SIMPLE tags eq_ref PRIMARY PRIMARY 4 lists_to_users.tag_id 1
1 SIMPLE users eq_ref email_2 email_2 302 contacts.email 1
还有查询本身:
SELECT `contacts`.*, `lists`.`name` AS `group`, `lists`.`id` AS `group_id`, `lists`.`shared_yn`, `tags`.`name` AS `context`, `tags`.`id` AS `context_id`, `tags`.`color` AS `context_color`, `users`.`id` AS `user_id`, `users`.`avatar`
FROM `contacts`
LEFT JOIN `lists` ON lists.id=contacts.list_id
LEFT JOIN `lists_to_users` ON lists_to_users.list_id=lists.id AND lists_to_users.user_id='1' AND lists_to_users.creator='1'
LEFT JOIN `tags` ON tags.id=lists_to_users.tag_id
INNER JOIN `users` ON users.email=contacts.email
WHERE (contacts.user_id='1')
ORDER BY `contacts`.`name` ASC
(我所说的子句是'users'表上的最后一个INNER JOIN)
查询在 MySQL 5.1 数据库上运行,如果有影响的话。
有没有人知道为什么在这种情况下 LEFT JOIN 的查询优于 INNER JOIN 的查询?
更新:由于 Tomalak 建议我使用的小表使 INNER JOIN 更加复杂,我创建了一个包含一些模拟数据的测试数据库。 'users' 表是 5000 行,contacts 表是 ~500,000 行。结果是一样的(时间也没有改变,当您考虑到现在的表要大得多时,这令人惊讶)。
我还在联系人表上运行了 ANALYZE 和 OPTIMIZE。没有任何明显的区别。
【问题讨论】:
-
您是否尝试先放置内部连接?
-
我有,它确实将查询速度提高了 20%,但仍然比 LEFT JOIN 慢
-
尝试按顺序构建每个查询(加入一张表,测量,加入下一张等)也许这有助于您确定缓慢的操作。
-
问题不在于速度(仍然相当快),而在于几乎完全相似的查询的执行时间差异 - 更快的是 LEFT JOIN,这对我来说是莫名其妙的
-
是的,我已经看到它几乎没有什么不同。但是当你只是加入用户和联系人时,它仍然这样做吗?您有关于contacts.email 的索引吗?
标签: mysql database performance join