【发布时间】:2021-10-10 07:31:59
【问题描述】:
MySQL 版本为 8.0.23
创建表并插入数据
CREATE TABLE `test_update` (
`id` int NOT NULL ,
`column1` varchar(20) DEFAULT NULL,
`column2` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into test_update values (1, 'a', 'test1');
insert into test_update values (2, 'b', 'test2');
insert into test_update values (3, 'c', 'test3');
insert into test_update values (4, 'd', 'test4');
insert into test_update values (5, 'e', 'test5');
insert into test_update values (6, 'f', 'test6');
insert into test_update values (7, 'g', 'test7');
insert into test_update values (8, 'h', 'test8');
insert into test_update values (9, 'i', 'test9');
insert into test_update values (10,'j', 'test10');
当我通过使用column2选择column1时,说明show mysql使用扫描全表,我认为这是合理的
mysql> explain select column1 from test_update where column2='test8';
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | test_update | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 10.00 | Using where |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
但是当我更新column1时,说明show mysql使用主键,它是一个非索引列,这是为什么呢?
mysql> explain update test_update set column1='z' where column2='test8';
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
| 1 | UPDATE | test_update | NULL | index | NULL | PRIMARY | 4 | NULL | 10 | 100.00 | Using where |
+----+-------------+-------------+------------+-------+---------------+---------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
【问题讨论】:
-
主索引是聚簇一,扫描它和扫描表是一样的。它用于 UPDATE 是因为服务器必须首先收集要更新的行的 PK 值,然后更新它们。
-
@Hedwig 。 . .行数太少,以至于 MySQL 可能会认为索引对
select没有用处。由于锁定和日志记录,updates 的索引使用不同。您可能想在有数千行而不是 10 行的表上尝试此操作。 -
@GordonLinoff,这不是我阅读问题的方式。两种情况下的 where 子句都不包含带索引的列 - 为什么“column2='test8'”会在主键上使用索引?
-
@Akina 那么,mysql 还是会扫描全表进行更新?
-
@GordonLinoff ,我在表中插入了 40,000 行,解释还是一样
标签: mysql sql indexing sql-execution-plan