【发布时间】:2021-05-27 18:09:11
【问题描述】:
如果我不锁定表,count(*) 的性能很糟糕,如下所示:
mysql> select count(*) from titles;
+----------+
| count(*) |
+----------+
| 443308 |
+----------+
1 row in set (8.79 sec)
mysql> explain select count(*) from titles;
+----+-------------+--------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | titles | NULL | index | NULL | PRIMARY | 209 | NULL | 442843 | 100.00 | Using index |
+----+-------------+--------+------------+-------+---------------+---------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
看起来很正常。但是当我锁表的时候,count(*)的表现却是那么的快。
mysql> lock tables titles read;
Query OK, 0 rows affected (0.00 sec)
mysql> select count(*) from titles;
+----------+
| count(*) |
+----------+
| 443308 |
+----------+
1 row in set (0.13 sec)
锁表后count的操作会发生什么?
2021-5-29 更新:
mysql> show index from titles;
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible | Expression |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
| titles | 0 | PRIMARY | 1 | emp_no | A | 301411 | NULL | NULL | | BTREE | | | YES | NULL |
| titles | 0 | PRIMARY | 2 | title | A | 441772 | NULL | NULL | | BTREE | | | YES | NULL |
| titles | 0 | PRIMARY | 3 | from_date | A | 442843 | NULL | NULL | | BTREE | | | YES | NULL |
| titles | 1 | idx_emp_no | 1 | emp_no | A | 300876 | NULL | NULL | | BTREE | | | YES | NULL |
+--------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+------------+
4 rows in set (0.04 sec)
mysql> explain select count(*) from titles;
+----+-------------+--------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | titles | NULL | index | NULL | idx_emp_no | 4 | NULL | 442835 | 100.00 | Using index |
+----+-------------+--------+------------+-------+---------------+------------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql> select count(*) from titles;
+----------+
| count(*) |
+----------+
| 443304 |
+----------+
1 row in set (8.79 sec)
我创建了一个较小的索引。但它没有任何变化。
【问题讨论】:
-
你能按相反的顺序试试这个吗(例如:第一个带锁的查询,然后没有锁的查询)它基本上可能是查询缓存的产物。此外,使用哪个表 ENGINE 可能会影响查询时间(INNODB MISAM)
-
@F.Igor。我试过很多次。没有什么不同的。它使用 InnoDB。也许我应该检查一下缓存是否正常?
-
但是我没有打开查询缓存。也许当我锁定表时它会打开查询缓存?
-
@F.Igor - 如果涉及查询缓存,则不需要 130 毫秒,而更像是 1 毫秒。相反,它可能是 buffer_pool 做缓存。
-
什么版本的mysql?