MySQL 删除几条记录需要很多 (40) 秒,而相同数据的 SELECT 很快

MySQL DELETE takes many (40) seconds for few records while a SELECT of the same data is fast

任何人都可以解释为什么 DELETE 语句需要更多时间来执行吗?我们没有创建任何 TRIGGER 或 CASCADE。从 5.5 迁移到 8.0 时,我们开始注意到这个问题。是不是8.0调参的问题?

DELETE s FROM storefront s LEFT JOIN MASTER m  ON m.userid=s.userid WHERE m.userid IS NULL

9 row(s) affected 
Execution Time : 40.816 sec
Transfer Time  : 0.001 sec
Total Time     : 40.817 sec

同时,SELECT语句只需要几毫秒。

SELECT s.userid FROM storefront s LEFT JOIN MASTER m  ON m.userid=s.userid WHERE m.userid IS NULL

Total Time     : 0.05 sec

如有任何帮助,我们将不胜感激。我们有更好的服务器硬件,16 GB RAM。

这里是 DELETE 语句的 PROFILING 信息。

It is CPU_user(19.046875 seconds) and CPU_system(43.156250 seconds) taking most of the time out of the total execution time 50.24 seconds ....

这不是答案,但它可以帮助找出花费了这么多时间的地方。使用分析

SET PROFILING=ON;

Manual

**sample**

mysql> SET PROFILING=ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select * from photons where photons >= 100;
+----+---------------------+---------+
| id | mytime              | photons |
+----+---------------------+---------+
|  1 | 2020-02-26 12:00:00 |     100 |
|  3 | 2020-02-26 12:01:00 |     100 |
|  4 | 2020-02-26 12:05:00 |     200 |
+----+---------------------+---------+
3 rows in set (0.01 sec)

mysql> SHOW PROFILE ALL;
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+
| Status               | Duration | CPU_user | CPU_system | Context_voluntary | Context_involuntary | Block_ops_in | Block_ops_out | Messages_sent | Messages_received | Page_faults_major | Page_faults_minor | Swaps | Source_function       | Source_file          | Source_line |
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+
| starting             | 0.000130 | 0.000071 |   0.000057 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | NULL                  | NULL                 |        NULL |
| checking permissions | 0.002022 | 0.000127 |   0.000103 |                 2 |                   0 |          160 |             0 |             0 |                 0 |                 2 |                 1 |     0 | check_access          | sql_authorization.cc |         802 |
| Opening tables       | 0.000474 | 0.000040 |   0.000033 |                 1 |                   0 |            8 |             0 |             0 |                 0 |                 1 |                 1 |     0 | open_tables           | sql_base.cc          |        5715 |
| init                 | 0.000043 | 0.000023 |   0.000020 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | handle_query          | sql_select.cc        |         121 |
| System lock          | 0.000811 | 0.000046 |   0.000035 |                 2 |                   0 |           16 |             0 |             0 |                 0 |                 2 |                 2 |     0 | mysql_lock_tables     | lock.cc              |         323 |
| optimizing           | 0.000474 | 0.000027 |   0.000023 |                 1 |                   0 |            8 |             0 |             0 |                 0 |                 1 |                 1 |     0 | optimize              | sql_optimizer.cc     |         151 |
| statistics           | 0.000027 | 0.000014 |   0.000012 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | optimize              | sql_optimizer.cc     |         367 |
| preparing            | 0.000763 | 0.000044 |   0.000036 |                 2 |                   0 |           16 |             0 |             0 |                 0 |                 2 |                 2 |     0 | optimize              | sql_optimizer.cc     |         475 |
| executing            | 0.000007 | 0.000003 |   0.000003 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | exec                  | sql_executor.cc      |         119 |
| Sending data         | 0.000103 | 0.000057 |   0.000046 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | exec                  | sql_executor.cc      |         195 |
| end                  | 0.001408 | 0.000062 |   0.000050 |                 1 |                   0 |          248 |             0 |             0 |                 0 |                 1 |                 0 |     0 | handle_query          | sql_select.cc        |         199 |
| query end            | 0.000378 | 0.000029 |   0.000022 |                 1 |                   0 |            8 |             0 |             0 |                 0 |                 1 |                 1 |     0 | mysql_execute_command | sql_parse.cc         |        4946 |
| closing tables       | 0.000409 | 0.000022 |   0.000020 |                 1 |                   0 |            8 |             0 |             0 |                 0 |                 1 |                 1 |     0 | mysql_execute_command | sql_parse.cc         |        4998 |
| freeing items        | 0.000030 | 0.000017 |   0.000012 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | mysql_parse           | sql_parse.cc         |        5610 |
| cleaning up          | 0.000026 | 0.000014 |   0.000012 |                 0 |                   0 |            0 |             0 |             0 |                 0 |                 0 |                 0 |     0 | dispatch_command      | sql_parse.cc         |        1924 |
+----------------------+----------+----------+------------+-------------------+---------------------+--------------+---------------+---------------+-------------------+-------------------+-------------------+-------+-----------------------+----------------------+-------------+
15 rows in set, 1 warning (0.00 sec)

mysql> 

关键词是"MyISAM"。 可能需要很长时间的原因有很多。

(我假设两个 table 都在 userid 上有一个索引?并且列定义相同?)

  • SELECT 会非常快,因为它只会使用索引来查找有问题的用户 ID。 0.05 秒几乎是 "too slow".
  • MyISAM 将在 DELETE 期间执行 table 锁定。
  • MyISAM 将每一行存储在 .MYD 文件中的某处。索引在 .MYI 文件中,即使对于主键也是如此。
  • 我认为通过更改行的初始字节来删除行。 (实际上是一个字节,其唯一目的是表示已删除。
  • 在 MyISAM 中,通常,一行是 .MYD 中的连续字节流。删除和一些更新将在 .MYD 中留下漏洞。
  • 插入更喜欢先填补漏洞,如果失败则增加文件。请注意,大行将是片段的链接列表。这可能会导致越来越慢的全行选择。
  • Oracle 计划摆脱 MyISAM。

这些并没有真正解释40秒只删除9行。 请提供 SHOW CREATE TABLEEXPLAIN DELETE ...;可能有您遗漏或我错误假设的细节。

底线:改用 InnoDB,这些问题就会消失。