【问题标题】:Simple MySQL Subquery Performance简单的 MySQL 子查询性能
【发布时间】:2012-09-11 08:42:14
【问题描述】:

考虑 2 个 MySQL 查询:

SELECT ue.userid,e.courseid 
FROM (SELECT id,courseid FROM mdl_enrol WHERE status = 0 AND courseid IN (46)) e 
INNER JOIN (SELECT enrolid,userid FROM mdl_user_enrolments ) ue ON ue.enrolid = e.id 
INNER JOIN (SELECT userid FROM mdl_userdata) ud ON ue.userid = ud.userid

--

SELECT ue.userid,e.courseid 
FROM mdl_enrol e 
INNER JOIN mdl_user_enrolments ue ON ue.enrolid = e.id 
INNER JOIN mdl_userdata ud ON ue.userid = ud.userid
WHERE e.status = 0 AND e.courseid IN (46)

底部查询比顶部查询快得多,但为什么呢?我已经读过,为了提高性能,您应该只选择您需要的列。此外,对我来说,顶级查询应该表现得更好,因为在每个 JOIN 中,您都在减少要加入的数据量。显然,我对数据库如何工作的理解是错误的,但如果有人能澄清这一点,我将不胜感激。 EXPLAIN 还确认底部查询要快得多。

非常感谢。

【问题讨论】:

  • "要提高性能,您应该只选择您需要的列" --- 为了提高性能,您应该避免使用子查询:-)

标签: mysql performance optimization


【解决方案1】:

在第一个查询中,mysql 应该从mdl_enrol 表中选择一个子集,并完成 mdl_user_enrolments 和mdl_userdata 到内存中。所以你在内存中选择了很多数据。完成之后 - 你加入数据。如果在连接并发送回客户端之前没有足够的内存来放置所有数据 - 然后会在硬盘驱动器上创建临时表。很可能 mysql 优化器不够酷,无法修复您的错误并尝试改进执行计划。这就是为什么它很慢。

而对于第二个查询,mysql 知道它究竟需要选择什么,并且只选择少量所需的数据。在这种情况下,可以使用索引(假设所有必要的索引都已创建)。所以它很快。

【讨论】:

  • 感谢您的回复。所以基本上如果你避免子查询,MySQL 不太可能需要创建临时表(一旦内存已满)。而且,在使用子查询时,索引效果较差,或者根本没有效果?
  • @paul78:有一些近似值 - 是的。查询优化过程非常困难,但避免子查询是一个很好的经验法则。虽然有子查询的有效案例 - 但这是另一回事;-)
猜你喜欢
  • 2014-04-06
  • 2015-07-12
  • 1970-01-01
  • 2011-10-13
  • 2017-09-02
  • 1970-01-01
  • 2011-03-25
  • 1970-01-01
  • 2018-02-09
相关资源
最近更新 更多