首页 > 解决方案 > 真的很长的mysql查询然后真的很快

问题描述

我对 SQL 查询有一个奇怪的行为,我真的不明白。

这是我的查询:

SELECT DISTINCT SU.a 
FROM SU 
    INNER JOIN SUT ON SUT.id = SU.tid 
WHERE SUT.id = 1 
AND SUT.status != 'DELETED' 
AND SU.status != 'DELETED' 
ORDER BY SU.a 
LIMIT 1;

第一次运行时,运行需要 8 分钟:

# Time: 2021-07-13T15:14:24.655492Z
# User@Host: a @ localhost []  Id: 12778294
# Schema: a  Last_errno: 0  Killed: 0
# Query_time: 472.123927  Lock_time: 0.000122  Rows_sent: 1  Rows_examined: 2055628  Rows_affected: 0  Bytes_sent: 132

但是当它第二次运行时,它真的很快:

# Time: 2021-07-13T15:27:24.286939Z
# User@Host: a @ localhost []  Id: 12786055
# Schema: a  Last_errno: 0  Killed: 0
# Query_time: 3.099028  Lock_time: 0.000124  Rows_sent: 1  Rows_examined: 2055642  Rows_affected: 0  Bytes_sent: 132

查询的解释似乎很好:

| id | select_type | table               | partitions | type  | possible_keys                                            | key                      | key_len | ref   | rows | filtered | Extra       |
+----+-------------+---------------------+------------+-------+----------------------------------------------------------+--------------------------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | SUT | NULL       | const | PRIMARY                                                  | PRIMARY                  | 4       | const |    1 |   100.00 | NULL        |
|  1 | SIMPLE      | SU         | NULL       | index | u_SU_a,idx_SUT_status | u_SU_a | 8       | NULL  | 4725 |     0.08 | Using where |
+----+-------------+---------------------+------------+-------+----------------------------------------------------------+--------------------------+---------+-------+------+----------+-------------+

两次执行之间的差异非常大。主机是一个大型 VM,在 Azure 上具有 55G 内存和 SSD Premium(P30 - 5000 IOPS,200 MBps)

标签: mysqlsql

解决方案


简短的回答:你看到的是正常的。

长答案:

如果第二次大约是 0.001 秒,我会怀疑查询缓存。但由于是 3 秒,我怀疑是其他缓存。

注意“Rows_examined”大约是 200 万。在非常糟糕的情况下,这可能是 2M 磁盘命中。使用 HDD,这可能需要大约 20K 秒;使用 SSD,可能不到 2K 秒。

由于第一次运行只用了 472 秒,我怀疑缓存(innodb_buffer_pool)在执行期间部分有用。可能只需要读取 47200 个块(如果使用 HDD)。

第二次运行显然在缓存中找到了所有必要的块,使其受 CPU 限制,没有 I/O。因此,只有 3 秒。

第三次运行将再次约为 3 秒。等等。

稍后,如果出现其他一些大查询并将块从缓存中取出,查询将再次变慢。

如果您提供SHOW CREATE TABLE每个表,我们可能会建议更好的索引,以使其在第一次和以后的时间都运行得更快。


推荐阅读