SELECT中的子查询或JOIN中的子查询?

时间:2015-02-11 16:45:06

标签: mysql correlated-subquery scalar-subquery

我有这种形式的MYSQL查询:

SELECT
    employee.name,
    totalpayments.totalpaid
FROM
    employee
    JOIN (
        SELECT
            paychecks.employee_id,
            SUM(paychecks.amount) totalpaid
        FROM
            paychecks
        GROUP BY
            paychecks.employee_id
         ) totalpayments on totalpayments.employee_id = employee.id

我最近发现这会以这种形式更快地返回:

SELECT
    employee.name,
    (
        SELECT
            SUM(paychecks.amount)
        FROM
            paychecks
        WHERE
            paychecks.employee_id = employee.id
    ) totalpaid
FROM
    employee

让我感到惊讶的是,速度会有所不同,而较低的查询会更快。我更喜欢上层开发,因为我可以独立运行子查询。

有没有办法让两个世界中最好的"快速的结果返回并且能够单独运行子查询?

2 个答案:

答案 0 :(得分:0)

可能,相关子查询能够有效地使用索引,这就是它快速的原因,即使子查询必须多次执行。

对于使用内联视图的第一个查询,导致MySQL创建派生表,对于大型集,这实际上是MyISAM表。

在MySQL 5.6.x及更高版本中,优化器可以选择在派生表上添加索引,如果这将允许ref操作并且ref操作的估计成本低于嵌套循环扫描。

我建议您尝试使用EXPLAIN查看访问计划。 (根据您的性能报告,我怀疑您运行的是MySQL 5.5或更早版本。)


如果employees中有行paychecks中没有匹配的行,则这两个语句并不完全等效。

可以完全避免子查询获得等效结果:

SELECT e.name
     , SUM(p.amount) AS total_paid
  FROM employee e 
  JOIN paychecks p
    ON p.employee_id = e.id
 GROUP BY e.id

(使用内部联接获取与第一个查询等效的结果,使用LEFT外部联接等效于第二个查询。将SUM()聚合包装在IFNULL函数中如果在薪水中找不到具有非空值amount的匹配行,则希望返回零值而不是NULL值。)

答案 1 :(得分:0)

Join基本上是笛卡尔积,这意味着表A的所有记录将与表B的所有记录组合。输出将是

number of records of table A * number of records of table b =rows in the new table
10 * 10 = 100

并且在这100条记录中,将在查询中返回与过滤器匹配的记录。

在嵌套查询中,有一个示例内部查询,内部查询的记录总大小将是outter查询的输入,这就是嵌套查询比连接更快的原因。