当评测记录的执行时间小于1秒时,30秒以上的MySQL SELECT查询延迟是什么原因?

当评测记录的执行时间小于1秒时,30秒以上的MySQL SELECT查询延迟是什么原因?,mysql,select,query-optimization,amazon-rds,amazon-aurora,Mysql,Select,Query Optimization,Amazon Rds,Amazon Aurora,我正在试图弄明白为什么在一个包含大量行和索引的非常臃肿的表上使用一个带有LIMIT 1子句的简单select有时需要30多秒甚至2分钟,有时需要在AWS RDS Aurora实例上执行。这是一个writer实例 这似乎只发生在客户端的第一个查询中,只发生在查看数十万行的特定select上,有时也会发生 查询的形式如下: SELECT some_table.col1, some_table.col2, some_table.col3, some_table.col4, MAX(some_ta

我正在试图弄明白为什么在一个包含大量行和索引的非常臃肿的表上使用一个带有LIMIT 1子句的简单select有时需要30多秒甚至2分钟,有时需要在AWS RDS Aurora实例上执行。这是一个writer实例

这似乎只发生在客户端的第一个查询中,只发生在查看数十万行的特定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;
和“解释”输出:

+----+-------------+---------------+------+---------------+---------+---------+-------+--------+-------+
| 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中记录的相同查询:

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

更多信息

从Performance Insights检查和发送的行:

显示创建表输出:


可能的解释是:

查询执行延迟,因为它正在等待锁定。甚至像SELECT这样的只读查询也可能需要等待元数据锁。 查询必须检查数十万行,从存储中读取这些行需要时间。极光应该有快速的存储,但它不可能是零成本的。 Aurora实例上的系统负载太高,因为它正在与正在运行的其他查询竞争。 Aurora实例上的系统负载太高,因为主机由其他Amazon客户拥有的其他Aurora实例共享。这种情况有时被称为“吵闹的邻居”,实际上你无法阻止它。亚马逊在同一硬件上为不同的客户自动对虚拟机进行联合。 将结果集传输到客户端需要很长时间。由于您使用的是LIMIT 1,所以这一行必须非常大才能占用30秒的时间,否则您的客户端必须处于非常缓慢的网络上。
第一次运行查询时,查询缓存不相关。随后执行同一查询的速度会更快,直到结果从缓存中移出后的某个时间,或者如果该表中的任何数据被更新,这将强制将针对该表的所有查询的结果从查询缓存中逐出。

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

如果要运行一个简单的函数,如SELECT*FROMTABLEA LIMIT 1;然后,数据库将向您显示它遇到的第一行,并在那里终止,从而快速返回

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

你可以在前面的问题中阅读更多关于这方面的内容;

如果您在最后运行相同的查询而没有限制1,您可能会发现返回结果所需的时间大致相同


正如您在评论中所提到的,最好查看模式,并找出如何修改此查询以提高效率。

作为起点-但可能不相关:这在标准SQL中不是有效的查询。select子句中有聚合列和非聚合列,但没有group by子句。谢谢,我不知道这件事!该查询来自ORM,但我想知道是否可以做一些调整来解决这个问题。向我们展示实际的查询并显示CREATE TABLE。该表使用的是什么引擎?它使用的是InnoDB
SHOW VARIABLES LIKE 'query_cache%';
SHOW GLOBAL STATUS LIKE 'Qc%';
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