为何相同查询在MySQL中比MariaDB慢?执行计划扫行更少却耗时久
MySQL与MariaDB同查询性能差异原因分析
我搭建了结构和数据完全一致的MySQL与MariaDB环境,执行同一条SQL查询时,MySQL耗时84.6042秒,远高于MariaDB的7.3797秒;且MySQL执行计划显示扫描行数更少。
查询语句
SELECT t.AccountCode AS Code, t.AccountDescription AS Description, t.Payment AS Total, COALESCE(SUM(l.DebitAmount - l.CreditAmount), 0.0) AS Balance FROM Ledgers AS l INNER JOIN ( SELECT m.AccountCode, m.AccountDescription, COALESCE(SUM(l0.CreditAmount), 0.0) AS Payment FROM Ledgers AS l0 INNER JOIN Masters AS m ON (l0.AccountCode = m.AccountCode) AND ((l0.CompanyCode = m.BranchCode) OR (l0.CompanyCode IS NULL AND m.BranchCode IS NULL)) WHERE (l0.CreationDate >= '2022-07-01' AND l0.CreationDate < '2022-07-02') AND (l0.CompanyCode = '029') AND (l0.Type IN ('CRV', 'BRV') AND l0.CreditAmount > 0.0) GROUP BY m.AccountCode, m.AccountDescription ) AS t ON l.AccountCode = t.AccountCode WHERE (l.CreationDate >= '2022-07-01' AND l.CreationDate < '2022-07-02') AND (l.TransactionYear = '2022-2023') AND (l.CompanyCode = '029') GROUP BY t.AccountCode, t.AccountDescription, t.Payment ORDER BY t.AccountCode;
执行计划
MariaDB执行计划(耗时7.3797秒)

MySQL执行计划(耗时84.6042秒)

性能差异的核心原因
- 优化器策略与成本估算差异:MySQL和MariaDB的优化器分支独立发展,对复杂查询的成本计算模型不同。针对查询中
(l0.CompanyCode = m.BranchCode) OR (l0.CompanyCode IS NULL AND m.BranchCode IS NULL)这类OR连接条件,MariaDB优化器可能生成了更高效的执行路径,而MySQL可能因对该条件的成本估算偏差,选择了看似扫描行数少但实际IO/计算开销更高的计划。 - 子查询与聚合处理效率:MariaDB对包含聚合的子查询可能采用了更优的物化或提前过滤策略,减少了后续关联的数据量;MySQL可能在子查询物化时产生了额外的临时表开销,或聚合操作的内存利用效率更低,导致耗时增加。
- 索引利用细节:虽然MySQL扫描行数更少,但如果它使用的索引需要频繁回表读取数据,而MariaDB选择的索引覆盖度更高(包含查询所需的所有字段),会大幅减少IO操作,最终MariaDB整体耗时更短。
- 连接算法选择:MariaDB可能针对该查询选择了哈希连接等高效算法,而MySQL可能采用了嵌套循环连接,在数据量较大时,后者的耗时会显著上升。
验证与优化建议
- 确认两张数据库中
Ledgers和Masters表的索引(类型、字段顺序、覆盖度)完全一致; - 检查执行计划中的
Using temporary、Using filesort标记,若MySQL出现这些,说明存在临时表或文件排序开销,可通过调整索引或改写查询优化; - 对比两者的优化器参数(如
optimizer_switch),查看是否有影响查询计划的配置差异; - 尝试改写查询:将OR条件拆分为两个UNION查询,或把子查询转换为JOIN形式,观察性能差异是否缩小。
内容的提问来源于stack exchange,提问作者Ãfsħąl Ãtħąr
相关产品推荐
相关产品推荐

