当分析记录执行时间 <1 秒时,有什么可以解释 30 秒以上 MySQL SELECT 查询延迟?

What could explain a 30+ second MySQL SELECT query latency when profiling records an execution time of <1 second?

我想弄清楚为什么带有 LIMIT 1 子句的简单 select(诚然,在具有大量行和索引的非常臃肿的 table 上)有时在 AWS RDS Aurora 实例上执行需要 30 多秒(有时甚至 2 分钟)。这是在编写器实例上。

它似乎发生在来自客户端的第一个查询中,仅在查看数十万行的特定 select 上发生,而且只是有时发生。

查询格式为:

SELECT some_table.col1, some_table.col2, some_table.col3, some_table.col4, 
  MAX(some_table.col2) AS SomeValue 
FROM some_table 
WHERE some_table.col3=123456 LIMIT 1;

和'explain'输出:

+----+-------------+---------------+------+---------------+---------+---------+-------+--------+-------+
| id | select_type | table         | type | possible_keys | key     | key_len | ref   | rows   | Extra |
+----+-------------+---------------+------+---------------+---------+---------+-------+--------+-------+
|  1 | SIMPLE      | some_table    | ref  | col1          | col1    | 4       | const | 268202 | NULL  |
+----+-------------+---------------+------+---------------+---------+---------+-------+--------+-------+

我设法重现了问题并在 PhpMyAdmin 中捕获了查询的配置文件。 PhpMyAdmin 记录查询执行时间为 30.1 秒,但分析器显示执行本身花费的时间不到一秒:

所以看起来执行本身并没有花费很多时间;是什么导致了这个延迟问题?我还发现 RDS Performance Insights 中记录了相同的查询:

这似乎发生在一系列相同或相似查询中的第一个查询中。可能是缓存问题吗?我已经尝试 运行 RESET QUERY CACHE; 试图重现延迟但没有成功。如果有帮助,很乐意提供有关基础架构的更多信息。

更多信息

SHOW VARIABLES LIKE 'query_cache%';

SHOW GLOBAL STATUS LIKE 'Qc%';

检查并发送的行(来自 Performance Insights):

SHOW CREATE TABLE 输出:

CREATE TABLE `some_table` (
`col1` int(10) unsigned NOT NULL AUTO_INCREMENT,
`col2` int(10) unsigned NOT NULL DEFAULT '0',
`col3` int(10) unsigned NOT NULL DEFAULT '0',
`col4` int(10) unsigned NOT NULL DEFAULT '0',
`col5` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`col6` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`col7` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`col1`),
KEY `col2` (`col2`),
KEY `col3` (`col3`),
KEY `col4` (`col4`),
KEY `col6` (`col6`),
KEY `col7` (`col7`)
) ENGINE=InnoDB AUTO_INCREMENT=123456789 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

可能的解释是:

  • 查询延迟执行,因为它正在等待锁定。即使像 SELECT 这样的只读查询也可能需要等待元数据锁定。
  • 查询必须检查数十万行,从存储中读取这些行需要时间。极光应该有快速存储,但它不可能是零成本。
  • Aurora 实例上的系统负载过高,因为它正在与您正在 运行 宁的其他查询竞争。
  • Aurora 实例的系统负载过高,因为主机被其他亚马逊客户拥有的其他Aurora 实例共享。这种情况有时被称为“吵闹的邻居”,您几乎无能为力。 Amazon 自动在同一硬件上为不同客户托管虚拟机。
  • 将结果集传输到客户端需要很长时间。由于您使用 LIMIT 1,单行必须很大才能花费 30 秒,否则您的客户端必须在非常慢的网络上。

第一次 运行 查询时,查询缓存不相关。随后执行相同的查询会更快,直到结果被从缓存中逐出后的某个时间,或者如果 table 中的任何数据被更新,这会强制所有查询的结果针对 table 将从查询缓存中逐出。

在这种情况下,您对LIMIT函数的理解似乎不太正确。

如果您要 运行 一个像 SELECT * FROM tablea LIMIT 1; 这样的简单函数,那么数据库会向您显示它遇到的第一行并在那里终止,让您快速 return .

但是在上面的示例中,您同时具有聚合函数和 WHERE 子句。 因此,为了使您的数据库return第一行,它必须首先return整个数据集,然后计算出第一行是什么。

您可以在这个较早的问题中阅读更多相关信息; https://dba.stackexchange.com/a/62444

如果您要 运行 同样的查询但最后没有 limit 1,您可能会发现 return 需要大约相同的时间才能得到结果.

正如您在评论中提到的,最好查看架构并弄清楚如何修改此查询以提高效率。