Nrich's blog Nrich's blog
首页
  • Java
  • Golang
  • 深度学习
  • Git
  • Linux
  • DataStructure
  • CloudNative
  • Redis
  • MySQL
  • 路由劫持
GitHub (opens new window)

Nrich

小聪明
首页
  • Java
  • Golang
  • 深度学习
  • Git
  • Linux
  • DataStructure
  • CloudNative
  • Redis
  • MySQL
  • 路由劫持
GitHub (opens new window)
  • Redis

  • MySQL

    • 专栏:MySQL 实战 45 讲

      • 基础架构:一条SQL查询语句是如何执行的?
      • 日志系统:一条SQL更新语句是如何执行的?
      • 事务隔离
      • 深入浅出索引
      • 全局锁、表级锁和行锁
      • change buffer
      • MySQL为什么有时候会加错索引
      • 怎么给字符串字段加索引
  • 中间件
  • MySQL
  • 专栏:MySQL 实战 45 讲
Nrich
2023-05-25

MySQL为什么有时候会加错索引

参考:10 MySQL为什么有时候会选错索引?| 极客时间 (opens new window) 其实本文没有解释很多原理,本文的初衷只是分享了几个解决方法,或许可以在碰到类似情况的时候,有一些思路。

我们知道在 MySQL 中,一张表是可以支持多个索引的,但我们的 SQL 语句并不会主动指定使用哪个索引,也就是说,使用哪个索引时由 MySQL 来确定的。

不过有时候我们可能碰到这样的情况:一条本来可以执行得很快的语句,却由于 MySQL 选错了索引,而导致执行速度变得很慢。

下面看一个例子。我们建一个简单的表,有 a、b 两个字段,并分别建立索引:

CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `a` (`a`),
  KEY `b` (`b`)
) ENGINE=InnoDB;
1
2
3
4
5
6
7
8

然后,我们往表 t 中插入 10 万行记录,取值按整数递增,即:(1,1,1),(2,2,2),(3,3,3) 直到 (100000,100000,100000)。如下是使用存储过程来实现这个插入数据的逻辑的:

delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=100000)do
    insert into t values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();
1
2
3
4
5
6
7
8
9
10
11
12

接下来,我们分析一条 SQL 语句:

mysql> select * from t where a between 10000 and 20000;
1

你一定会说,这个语句还用分析吗,很简单呀,a 上有索引,肯定是要使用索引 a 的。没错,图 1 显示的就是使用 explain 命令看到的这条语句的执行情况。

20230508111539
图 1 使用 explain 命令查看语句执行情况

从图 1 看上去,这条查询语句的执行也确实符合预期,key 这个字段值是’a’,表示优化器选择了索引 a。

编辑 (opens new window)
上次更新: 2023/05/25, 09:07:23
change buffer
怎么给字符串字段加索引

← change buffer 怎么给字符串字段加索引→

最近更新
01
YAML、Pod、Job、CronJob、ConfigMap、Secret
06-06
02
Kubernetes 的安装与基本架构
06-04
03
初识容器
05-30
更多文章>
Theme by Vdoing | Copyright © 2022-2023 Nrich | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式