当评测记录的执行时间小于1秒时,30秒以上的mysql select查询延迟是怎么解释的?

kx5bkwkv  于 2021-06-15  发布在  Mysql
关注(0)|答案(2)|浏览(550)

我想知道为什么一个简单的选择 LIMIT 1 子句(不可否认,在一个包含大量行和索引的非常臃肿的表上)有时在awsrds aurora示例上执行需要30多秒(有时甚至2分钟)。这是一个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中记录的相同查询:

对于一系列相同或相似的查询中的第一个查询,似乎会发生这种情况。可能是缓存问题吗?我试过跑步 RESET QUERY CACHE; 试图重现潜伏期但没有成功。如果有帮助的话,我很乐意提供更多关于基础设施的信息。
更多信息

SHOW VARIABLES LIKE 'query_cache%';

SHOW GLOBAL STATUS LIKE 'Qc%';


检查并发送的行(来自性能分析):
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
zaqlnxep

zaqlnxep1#

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

bvjxkvbb

bvjxkvbb2#

看来你对 LIMIT 函数在这种情况下不太正确。
如果你运行一个简单的函数 SELECT * FROM tablea LIMIT 1; 然后数据库会显示它遇到的第一行,并在那里终止,给您一个快速返回。
但是,在上面的示例中,您有一个聚合函数和一个where子句。因此,为了让数据库返回第一行,它必须首先返回整个数据集,然后计算出第一行是什么。
你可以在前面的问题中阅读更多关于这方面的内容;https://dba.stackexchange.com/a/62444
如果你运行同样的查询 limit 1 最后,您可能会发现返回结果所需的时间大致相同。
正如您在评论中提到的那样,最好查看模式并找出如何修改此查询以提高效率。

相关问题