查询成本是 MySQL 查询优化的最佳指标吗?

Posted

技术标签:

【中文标题】查询成本是 MySQL 查询优化的最佳指标吗?【英文标题】:Is query cost the best metric for MySQL query optimization? 【发布时间】:2017-08-17 16:25:21 【问题描述】:

我正在优化我的 mysql 数据库中的查询。在使用 Visual Explain 并查看各种查询成本时,我反复发现违反直觉的值。使用更高效查找的操作(例如键查找)似乎比表面上效率较低的操作(例如全表扫描或全索引扫描)具有更高的查询成本。

这方面的示例甚至可以在 MySQL 手册中的 this page 上有关 Visual Explain 的部分中看到: 全表扫描的查询成本是基于键查找的查询成本的一小部分。我在自己的数据库中看到了完全相同的场景。

这一切对我来说似乎完全倒退了,并提出了一个问题:在优化查询时,我应该使用查询成本作为标准吗?还是我从根本上误解了查询成本?

【问题讨论】:

归根结底,“实际性能”通常是最重要的。估计的(和实际的)查询计划很好。另一方面,让相关查询快速运行通常是一项要求。 另外,我不确定问题是什么 - 基本 FTS 的成本本身没有意义,因为它只是回答查询所需信息的一部分。 (如果表有适当的索引和数据量,它应该从完全扫描更改为索引扫描:这一步实际上只是“构建初始 N [1000] 行”。在这种情况下,计划者认为表足够小或没有可用的索引。) 我了解查询的每个步骤在做什么以及它是如何做的。我不明白的是,查询规划器几乎无一例外地认为索引读取比非索引读取更昂贵,而常识会告诉您其他情况。例如,在我的数据库中,我发现一个查询正在执行全表扫描,所以我添加了一个适当的索引,然后规划器选择了该索引,但 EXPLAIN 显示查询成本在该更改之后上升 【参考方案1】:

MySQL 没有与优化相关的非常好的指标。比较好的一个是EXPLAIN FORMAT=JSON SELECT ...,但它有点神秘。

一些“严重”的缺陷:

LIMIT 很少做任何事情。 指数统计数据是粗略的,不允许分布不均。 (直方图即将推出。) 对于当前是否缓存数据/索引,以及是否使用旋转驱动器或 SSD,我们几乎没有做任何事情。

我喜欢这个,因为它可以让我比较两个公式/索引/等,即使对于时间几乎没用的小表也是如此:

FLUSH STATUS;
perform the query
SHOW SESSION STATUS LIKE "Handler%";

它提供准确计数(不像EXPLAIN)读取、写入(到临时表)等。它的主要缺陷是没有区分读取/写入花费了多长时间(由于缓存,索引查找等)。但是,它通常非常擅长指出查询是进行表/索引扫描还是查找还是多次扫描。

常规的EXPLAIN 无法指出多种类型,例如GROUP BY ORDER BY 可能发生的情况。并且“使用文件排序”并不一定意味着将任何内容写入磁盘。

【讨论】:

以上是关于查询成本是 MySQL 查询优化的最佳指标吗?的主要内容,如果未能解决你的问题,请参考以下文章

DBA的五款最佳SQL查询优化工具

Vertica 中解释查询的成本

MySQL性能优化的最佳经验

MySQL查询优化器工作原理解析

MySQL查询优化器工作原理解析

mysql之性能指标查询