mysql - MySQL中主键和多列索引的优先级?

标签 mysql sql

CREATE TABLE student (                                  
  id int(11) NOT NULL AUTO_INCREMENT,                   
  name varchar(128) DEFAULT NULL,                 
  age int(11) NOT NULL,
  update_time timestamp NULL DEFAULT CURRENT_TIMESTAMP 
    ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (id),                                   
       KEY idx_name_age (name,age),                         
       KEY idx_name_age_update_time (name,age,update_time) 
     ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

我使用EXPLAIN来获取索引在MySQL中如何工作的一些信息,当我像这样执行sql时,我发现一件事让我感到困惑:

EXPLAIN 
  SELECT * FROM springboot.student
    WHERE id>1 AND id <5 AND NAME = 'tank' AND age =23 ;

结果:

id   select_type   table     type     possible_keys    key            key_len   ref             rows  Extra        
------  -----------  -------  ------  ---------------------------------------------  ------------  -------  -----------  ------  -------------
1  SIMPLE       student  ref     PRIMARY,idx_name_age,idx_name_age_update_time  idx_name_age  391      const,const       1  Using where 

我想知道为什么我会遇到这个。

最佳答案

没有固有的优先级。您影响 SQL 优化器,但无法控制它。这实际上很好。基于规则的优化器已经过时相当长一段时间了,而基于成本的优化器则风靡一时。

所发生的情况是,[基于成本的] SQL 优化器会生成一个依赖于许多参数的执行计划。例如:

  • 表格的大小。
  • 存在索引。
  • 每列值的分布。
  • 过滤条件的选择性。
  • 表格统计信息的最新情况。
  • 等等

您似乎希望使用主键通过索引读取表。转换为优化器术语,您想要:

  • 访问:通过主键索引,使用索引范围扫描
  • 过滤:按 NAME = 'tank' AND 年龄 = 23

但是优化器决定做一些不同的事情:

  • 访问:通过索引(姓名、年龄),使用索引查找
  • 过滤:按主键索引。

一般来说,索引查找比索引范围扫描快得多。也许这就是优化器选择第二个的原因。

你真的测量过执行时间吗?请记住,计划不是查询。测量,测量,测量。

关于mysql - MySQL中主键和多列索引的优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51053571/

相关文章:

python - 检查冲突/学生不能在同一类(class)中注册两次

php - 在 SQL 查询结束时使用 implode 和 concatenate

mysql - 访问虚拟主机时 SQL 访问被拒绝

SQL查询球员平均热连胜持续时间

mysql - 获取数据组中的最小最大值

mysql - 查找所有以数字开头的条目的最有效 MySQL 查询是什么?

python - Django 连接远程 Mysql OperationalError 2026

mysql - 错误 1215 外键约束

sql - 使用花括号和通配符转义 Oracle 文本

sql - postgresql 中的第一个和最后一个值聚合函数可以正确处理 NULL 值