mysql 巧妙的索引

文章目录


前言

MySQL索引是数据库管理系统中用于提高查询效率的一种数据结构。它们类似于书籍的目录,通过索引,数据库可以快速定位到所需的数据,而无需扫描整个表,很大提升了查询效率


一、索引类型

1、普通索引

  • 最基本的索引类型,没有任何限制。
  • 允许在定义索引的列中插入重复值和空值。

2、唯一索引

  • 索引列的所有值都只能出现一次,即必须唯一。
  • 允许有空值,但如果是组合索引,则列值的组合必须唯一。

3、主键索引

  • 为主键字段创建的索引。
  • 是一种特殊的唯一索引,不允许值重复或者值为空。
  • 一个表只能有一个主键索引。

4、组合索引(复合索引)

  • 将原表的多个列共同组成一个索引。
  • 只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。

5、全文索引(FULLTEXT索引)

  • 主要用于查找文本中的关键字。
  • 可以在CHAR、VARCHAR或TEXT类型的列上创建。
  • MySQL中MyISAM和InnoDB存储引擎支持全文索引(从MySQL 5.6版本开始)。

二、索引使用原则

1、列的离散度

  • 如果列的重复值越多,离散度就越低,重复值越少,离散度就越高。不建议在离散度低的列上建立索引,可能或者的效果成反比。
  • 比如性别只有男女两个值,如果建立单个列的索引,会发现查询效率反而变差了

2、联合索引

2.1、字段顺序:

  • 复合索引的字段顺序应与查询条件中的字段顺序一致(最左匹配),以确保索引能够完全匹配查询条件。

2.2、字段相关性:

  • 如果复合索引中的字段经常同时以AND方式出现在WHERE子句中,则可以建立复合索引。
  • 如果复合索引中的字段经常单独出现在WHERE子句中,则可以考虑将其分解为多个单字段索引。

2.3、字段数量:

  • 复合索引包含的字段数量应适中,过多的字段会增加索引的大小和维护成本,并可能导致索引失效。

3、列的稳定度

  • 避免在频繁更新的列上建立索引,因为更新操作需要维护索引结构,所以频繁更新的列上建立索引会增加数据库的维护成本。

4、列的查询率

  • 在建立索引或者联合索引时,应该首先选择最常用的查询条件作为第一列。这样可以最大程度地提高查询效率,减少数据扫描的次数。查询条件包括where、on、group by、order by 等

三、索引的两个技术升级

1、覆盖索引

在二级索引里面,不管是单列索引还是联合索引,如果select 的数据列只用从索引中就能够取得,不必从数据区中读取,这时候使用的索引就叫做覆盖索引,这样就避免了回表。

回表:

非主键索引,我们先通过索引找到主键索引的键值,再通过主键值查出索引里面没有的数据,它比基于主键索引的查询多扫描了一棵索引树,这个过程就叫回表

在MySQL中,可以使用EXPLAIN关键字来查看查询是否使用了覆盖索引。在EXPLAIN输出中,如果Extra列包含Using index,则表示查询使用了覆盖索引。例如:

复制代码
EXPLAIN SELECT department_id, name FROM employees WHERE department_id = 5;

如果Extra列中显示Using index,说明MySQL只使用索引就完成了查询,无需回表操作,这就是覆盖索引在发挥作用。

2、索引条件下推(Index Condition Pushdown,ICP)

下推: 其实是意思是把过滤的动作在存储引擎做完,而不需要到 Server 层过滤,从而减少不必要的回表操作。

生效条件:

  • 二级索引
  • innodb、myisam

假设有一个名为employees的表,表结构如下:

复制代码
CREATE TABLE Student(  
    id INT PRIMARY KEY,  
    name VARCHAR(100),  
    age INT,  
    addr VARCHAR(100),  
    INDEX idx_age_city(age, name)  
);

假设执行的sql语句为

复制代码
select * from Student where age = 13 and name like '%huihui1'

如果不使用索引条件下推,查询过程可能如下:

  • 1、MySQL解析SQL语句,并由优化器选择使用age索引进行扫描。
  • 2、存储引擎扫描age索引,找到所有满足 age = 13 条件的记录。
  • 3、对于每条满足 age = 13 条件的记录,通过主键进行回表操作,获取完整的行数据。
  • 4、在MySQL的Server层中的执行器对回表后的数据进行进一步过滤,检查 name like '%huihui1' 条件,筛选出符合条件的记录。

使用索引条件下推,查询过程将优化为:

  • 1、MySQL解析SQL语句,并由优化器选择使用age索引进行扫描。
  • 2、存储引擎扫描age索引,同时利用索引条件下推技术提前应用 name like '%huihui1' 条件,只返回同时满足age = 13 和name like '%huihui1' 条件的记录。
  • 3、对于符合条件的记录,通过主键进行回表操作(如果需要的话),获取完整的行数据(但在这个例子中,由于已经通过索引条件下推过滤了不符合条件的记录,所以回表操作的次数将大大减少)。

通过这个例子可以看出,索引条件下推能够显著减少回表操作的次数,从而提高查询性能

索引条件下推启停:

复制代码
SET optimizer_switch='index_condition_pushdown=on';  -- on 改成 off 表示禁用

四、索引失效条件

1、最左匹配原则失效:

  • 在复合索引中,查询条件没有使用最左边的索引字段,或者查询条件中的字段顺序与复合索引的字段顺序不一致。例如,如果有一个复合索引(name, code, address),查询条件中只使用了code或address,或者它们的顺序与索引顺序不匹配,那么索引可能无法被有效利用。

2、使用函数或计算操作:

  • 在查询条件中对索引字段进行了函数操作或计算,如LOWER(column)、DATE(column)等。这些操作会导致数据库无法直接使用索引,因为数据库无法预知函数或计算的结果。

3、LIKE通配符的使用:

  • 当使用LIKE进行模糊查询时,如果通配符(%)出现在字段的最左侧,索引可能会失效。例如,LIKE '%abc'会导致索引失效,因为数据库需要扫描整个字段来匹配模式。

4、OR条件和IN操作的不当使用:

  • 在OR运算中,如果其中一个条件使用了索引,而另一个条件没有使用索引,整个查询可能会导致索引失效。同样,IN操作中的值如果过多,也可能导致索引失效,因为数据库可能会选择进行全表扫描而不是使用索引。

5、数据类型不匹配(隐式转换):

  • 查询条件中的数据类型与索引字段的数据类型不匹配时,索引可能会失效。例如,如果索引字段是整数类型,而查询条件中使用了字符串类型,那么索引可能无法被利用。

总结

MySQL索引技术是提高数据库查询效率的重要手段。合理使用索引可以显著提升数据库性能,但也需要注意索引的维护成本和适用场景。

相关推荐
叁沐几秒前
MySQL 08 详解read view:事务到底是隔离的还是不隔离的?
mysql
wuxuanok2 分钟前
Web后端开发-分层解耦
java·笔记·后端·学习
周胡杰18 分钟前
鸿蒙arkts使用关系型数据库,使用DB Browser for SQLite连接和查看数据库数据?使用TaskPool进行频繁数据库操作
前端·数据库·华为·harmonyos·鸿蒙·鸿蒙系统
315356691319 分钟前
ClipReader:一个剪贴板英语单词阅读器
前端·后端
wkj00121 分钟前
navicate如何设置数据库引擎
数据库·mysql
ladymorgana21 分钟前
【Spring Boot】HikariCP 连接池 YAML 配置详解
spring boot·后端·mysql·连接池·hikaricp
赵渝强老师24 分钟前
【赵渝强老师】Oracle RMAN的目录数据库
数据库·oracle
暖暖木头26 分钟前
Oracle注释详解
数据库·oracle
neoooo42 分钟前
别慌,Java只有值传递——一次搞懂“为啥我改了它还不变”!
java·后端·spring
御控工业物联网43 分钟前
御控网关如何实现MQTT、MODBUS、OPCUA、SQL、HTTP之间协议转换
数据库·sql·http