mysql 删除数据的时候,会不会走索引?

一个用户表,字段 id,name,age,sex,work,city
联合索引为 (sex,city)
我要删除sex=男,city=北京的数据,会不会走联合索引

阅读 5.9k
4 个回答

在 mysql 中,如果涉及到的数据超过 20%,将不会使用索引,反之则会。
@zxdposter 你这个应该是翻译错了吧

简单实践

数据总条数是: 1602

符合条件sex,city条数: 女, 广州, 604

mysql> explain delete from  test_del_idx where sex="女" and city = "广州";
+----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table        | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | DELETE      | test_del_idx | NULL       | ALL  | idx_sex_city  | NULL | NULL    | NULL | 1602 |   100.00 | Using where |
+----+-------------+--------------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set (0.00 sec)

符合条件sex,city条数: 女, 惠州, 6

mysql> explain delete from  test_del_idx where sex="女" and city = "惠州";
+----+-------------+--------------+------------+-------+---------------+--------------+---------+-------------+------+----------+-------------+
| id | select_type | table        | partitions | type  | possible_keys | key          | key_len | ref         | rows | filtered | Extra       |
+----+-------------+--------------+------------+-------+---------------+--------------+---------+-------------+------+----------+-------------+
|  1 | DELETE      | test_del_idx | NULL       | range | idx_sex_city  | idx_sex_city | 773     | const,const |    6 |   100.00 | Using where |
+----+-------------+--------------+------------+-------+---------------+--------------+---------+-------------+------+----------+-------------+
1 row in set (0.00 sec)

实践环境和数据

环境-docker-mysql5.7

表和数据

应该会。

你可以 explain 一下看看。

查了很多资料,似乎索引用不用取决于数据库自己的判断。

does-mysql-use-index-on-delete,这里提到,在 mysql 中,如果涉及到的数据超过 20%,将不会使用索引,如果没到就会使用。

之前我们做数据库优化时,也遇到相似的情况,明明查询列存在索引,但是并没有触发,想要触发一定要强制指定使用索引才行。

因此我当时猜测,数据库有自己的方法判断,是否使用索引。

这是来自 mysql 的官方文档 描述。

Indexes are less important for queries on small tables, or big tables where report queries process most or all of the rows. When a query needs to access most of the rows, reading sequentially is faster than working through an index. Sequential reads minimize disk seeks, even if not all the rows are needed for the query.

翻译:

对于小表或报表查询处理大部分或所有行的大表的查询,索引不太重要。当查询需要访问大部分行时,顺序读取比通过索引更快。即使查询不需要所有行,顺序读取也可以最大限度地减少磁盘寻道。

这也一定程度上说明了上面第二句话。


最后我也没有在官方文档中找到 delete 完全不使用索引的描述。

大概率不会,看数据分布,当然还是explain看下最准。

如果数据量大的话建议不要直接delete where 这种区分度不高的字段,建议把id先查出来,再分批delete,避免造成长时间锁等待和主从延迟~

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏