查询计划中的行列令人困惑

时间:2016-04-18 17:19:03

标签: mysql sql performance

我有一个MySql查询

 SELECT TE.company_id, 
        SUM(TE.debit- TE.credit) As summation 
 FROM Transactions T JOIN Transaction_E TE2 
      ON (T.parent_id = TE2.transaction_id) 
 JOIN Transaction_E TE 
      ON (TE.transaction_id = T.id AND TE.company_id IS NOT NULL) 
 JOIN Accounts A 
      ON (TE2.account_id=A.id AND A.deactivated_timestamp=0) 
 WHERE (TE.company_id IN (1,2)) 
   AND A.user_id=2341 GROUP BY TE.company_id;

当我解释查询时,它的计划就像(摘要):

 | Select type | table | type | rows |
 -------------------------------------
 | SIMPLE      | A     | ref  | 2    |
 | SIMPLE      | TE2   | ref  | 17   |
 | SIMPLE      | T     | ref  | 1    |
 | SIMPLE      | TE    | ref  | 1    |

但是如果我对同一个查询(而不是SUM(..))执行count(*),那么它会显示特定company_id有~40k行。我不明白的是,为什么查询计划显示在处理至少40k行时扫描如此少的行。查询计划中的rows列代表什么?它不代表在该表中处理的行数吗?在这种情况下,它应该至多2 * 17 * 1 * 1 = 34行?

2 个答案:

答案 0 :(得分:0)

查询计划只显示对每个表所需的预期行数的高级判断,以满足最终结果。 它将被用作判断优化器如何看待'的工具。您的查询,并帮助它,以防查询性能更差或可以改进。

查询计划总是有可能是基于早期的统计快照构建的,因此不应该采用面值,特别是在处理基数时。

答案 1 :(得分:0)

好吧,首先让我们摆脱计算错误:

SELECT  TE.company_id, TE.summation
    FROM  
      ( SELECT  company_id,
                SUM(debit - credit) As summation
            FROM Transaction_E
            WHERE  company_id IN (1,2)
      ) TE
    JOIN Transactions T    ON TE.transaction_id = T.id
    JOIN Transaction_E TE2 ON T.parent_id = TE2.transaction_id
    JOIN Accounts A        ON TE2.account_id = A.id
      AND  A.deactivated_timestamp = 0
    WHERE  A.user_id = 2341;

您的查询可能在执行GROUP BY之前多次总结同一家公司。我的变体避免了总量的膨胀。

我摆脱了TE.company_id IS NOT NULL,因为它是多余的。

请参阅EXPLAIN对此的说明,然后让我们进一步讨论您关于EXPLAIN的问题。