【发布时间】:2021-05-16 16:07:40
【问题描述】:
我创建了一个 2TB 的 MySQL RDS,并在其中填充了 2 个总共 1.5TB 的表:
+----------+---------------------------+------------+
| Database | Table | Size in MB |
+----------+---------------------------+------------+
| stam_db | owl | 1182043.00 |
| stam_db | owl_owners | 393695.00 |
实例设置为 db.m6g.2xlarge 大小和 6000 预置 IOPS。
我运行此查询以返回前 10 行(它们都是不同的,没有重复的行):
SELECT DISTINCT *
FROM owl
ORDER BY
name
LIMIT 10;
令我惊讶的是,这个查询已经运行了 2 个小时... 更令人惊讶的是,AWS 的“可用存储空间”指标开始以 2.2GB/分钟的速度下降:
由于某种原因,Write IOPS 突然上升到每秒 600-700:
我有几个问题:
- 为什么 SELECT DISTINCT 语句会导致对数据库进行如此大量的写入?
- 为什么 SELECT DISTINCT 会尝试读取整个数据库,而不仅仅是前 10 行?
- 为什么 RDS 不使用 6000 分配的 IOPS?总 IOPS 仅为分配量的 40% 左右。
答案如下:
Q2) 我想我在https://www.percona.com/blog/2019/07/17/mysql-disk-space-exhaustion-for-implicit-temporary-tables/ 找到了解释-" 大部分时间需要排序阶段的查询需要依赖临时表。例如,当您使用 GROUP BY、ORDER BY 或 DISTINCT 时。这样的查询分两个阶段执行:第一个是收集数据并将它们放入临时表中,第二个是对临时表执行排序。”因此,即使是带有 ORDER BY 的常规 SELECT 也需要重新读取整个表
Q1) 大量写入是为查询创建的临时表造成的,可以达到原表的100%。
Q3) 看起来 MySQL 代码创建临时表的效率不足以利用整个 6000 IOPS
【问题讨论】:
-
LIMIT 10 只返回 10 行作为结果,但在返回前 10 行之前对所有行进行 seacrh
-
您的意思是 SELECT DISTINCT 在返回请求的行数之前读取整个表吗?常规的 SELECT 也有这种行为吗?
-
是的...这是常规行为 .. 有 distinct 子句或没有 distinct 子句 .. distinct 子句只是避免 resutl 中的重复行
-
哇...有没有办法在重新读取整个表格的情况下获得 10 行?
-
我想我在percona.com/blog/2019/07/17/…找到了解释-" 大部分时间需要排序阶段的查询需要依赖临时表。例如,当你使用GROUP BY时,ORDER BY或 DISTINCT。这样的查询分两个阶段执行:第一个是收集数据并将它们放入临时表中,第二个是对临时表执行排序。因此,即使是带有 ORDER BY 的常规 SELECT 也需要重新读取整个表
标签: mysql amazon-web-services amazon-rds