查询计划中的行列令人困惑
Posted
技术标签:
【中文标题】查询计划中的行列令人困惑【英文标题】:Rows column in Query Plan confusing 【发布时间】:2016-04-18 17:19:03 【问题描述】:我有一个 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 行?
【问题讨论】:
【参考方案1】:查询计划只是对满足最终结果的每个表所需的预期行数进行了高级判断。 它被用作判断优化器如何“看到”您的查询的工具,并在查询性能更差或可以改进的情况下提供一些帮助。
查询计划总是有可能是基于较早的统计数据快照构建的,因此不应从表面上看,尤其是在处理基数时。
【讨论】:
感谢您的回复,但它建议的内容(约 34 行)和最终的结果(40k 行)之间仍然存在巨大差异。它是如何得出这些数字的?这些数字现在在我看来是随机的【参考方案2】:好吧,首先让我们摆脱计算错误:
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
的问题。
【讨论】:
我尝试了您建议的查询。有两个问题:首先,结果不一样,其次,查询计划还有一行 DERIVED 选择类型,它会扫描约 40k 行以查找该派生选择 我觉得需要子查询才能获得正确的 SUM 值。是吗?以上是关于查询计划中的行列令人困惑的主要内容,如果未能解决你的问题,请参考以下文章