如何估计 MySQL 查询执行的 I/O 操作?

Cli*_*ote 13 mysql

在 Amazon 的 RDS 上,您为每 100 万个 I/O 请求支付大约 0.10 美元。我注意到对流量非常低的数据库的 I/O 请求数量非常多(以数十万计)。看到这个,我做了一些进一步的研究,发现这个问题描述了一个 6,000 个用户的网站,他每个月产生 8 亿个 I/O 请求,这将花费他大约 80 美元/月。

因此,我想提前知道一个 MySQL 查询会生成多少 I/O 操作,以及如何优化/最小化它们。有什么方法可以估计查询将执行多少 I/O 操作,以及我可以遵循的任何一般规则来使它们尽可能低吗?

Pau*_*ite 2

根据Raymond Nijland对问题的评论生成的社区 Wiki 答案

使用EXPLAIN。通过这种方式,您可以查看查询是否可能需要磁盘 IO。您需要避免在该列中出现额外的“使用临时”或“”使用临时;使用文件排序(请注意,文件排序是一个误导性的名称:如果结果集适合内存,则快速排序在内存中运行)”。

这很可能是由子查询/联合/order by/group by/...引起的如果你的结果很大并且创建了MyISAM基于磁盘的临时表,并且你需要对结果进行排序,那么你正在对结果进行排序基于 IO 读取和 IO 写入的快速排序算法进行设置。

MySQL 中的内部临时表使用中,您可以阅读 MySQL 何时需要创建基于磁盘的 MyISAM 表。也许您可以使用avg_row_length * rows(尽管请注意,解释中的值对于 InnoDB 引擎并不准确)来检查结果是否适合堆。请参阅SHOW TABLE STATUS 语法

一般来说,InnoDB 还是 MyISAM 更能避免 I/O 请求?

InnoDB会缓冲表数据和索引数据,而MyISAM只缓冲索引键。当解释列额外没有说“使用索引”时,需要对表数据进行 I/O 。

如果两者都使用索引:对于 InnoDB,如果缓冲区很热,它可以从内存加载数据。如果索引需要来自磁盘,则可以使用一个公式来计算选择、插入和更新所需的 IO 读取。从估计查询性能

对于小型表,您通常可以在一次磁盘查找中找到一行(因为索引可能已缓存)。对于更大的表,您可以估计,使用 B 树索引,您需要这么多次查找才能找到一行:

log(rows) / log(index_block_length / 3 * 2 / (index_length + data_pointer_length)) + 1
Run Code Online (Sandbox Code Playgroud)

InnoDB 索引更大,因为它将 PRIMARY / UNIQUE 键的数据存储到 KEY 索引中。这更快并且需要更少的 IO 查找,但您可以压缩 InnoDB 数据或索引。