文章目录
- 前言
- 一、索引类型
- 二、索引使用原则
- 三、索引的两个技术升级
-
-
- 1、覆盖索引
- [2、索引条件下推(Index Condition Pushdown,ICP)](#2、索引条件下推(Index Condition Pushdown,ICP))
-
- 四、索引失效条件
- 总结
前言
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索引技术是提高数据库查询效率的重要手段。合理使用索引可以显著提升数据库性能,但也需要注意索引的维护成本和适用场景。