Mysql 索引

1.基本概念:

在MySQL中,索引(Index)是用于提高查询速度的一种数据结构。索引类似于书的目录,通过建立索引,可以快速找到数据在表中的位置,而无需扫描整个表。索引在优化数据库查询性能方面起着非常重要的作用,但也会带来一些额外的存储空间开销和维护成本。

2.类型:

(1).主键索引:数据列不允许重复,不允许为NULL,一个表只有一个主键。

(2).唯一索引:数据列不允许重复,允许为NULL,一个表允许多个列创建唯一索引。

(3).普通索引:基本的索引类型,没有唯一性的限制,允许为NULL值。

(4).全文索引:是目前搜索引擎使用的一种关键技术,对文本的内容进行分词、搜索。

3.结构:

MySQL 索引的实现依赖于存储引擎,不同的存储引擎索引结构有所不同:

  • B-Tree 索引: 这是大多数存储引擎使用的默认索引类型,如 InnoDB 和 MyISAM。B-Tree 索引适用于全值匹配、范围查询、前缀匹配等。

  • Hash 索引: 只有 Memory 引擎支持的索引类型,适用于精确查询,不支持范围查询。其特点是查询速度极快,但由于不存储顺序信息,无法用于排序操作。

  • 全文索引(Full-Text): 使用倒排索引(Inverted Index),主要用于全文搜索。适用于大量文本内容的模糊查询。

  • R-Tree 索引: 主要用于空间数据的存储,常用于地理信息系统(GIS)

4.工作原理

MySQL 索引的实现基于数据结构,如 B-Tree(B+树)和哈希表:

  • B-Tree(B+树) 索引工作原理: B-Tree 是一种平衡树数据结构,节点按照关键字顺序排列,每个节点保存索引的关键字和数据指针。在查询时,MySQL 会从根节点开始搜索,通过比较关键字大小进入相应的子节点,直到查找到目标数据。这个过程通常是 O(log n) 的时间复杂度,非常高效。

  • Hash 索引工作原理: 哈希索引基于哈希表实现,将索引字段的值通过哈希函数转换为一个特定的地址,查找速度很快。适用于精确匹配查询,但不适用于范围查询。

聚簇索引:

按照主键或唯一约束条件来组织数据,查询效率高,但插入、更新和删除操作可能会影响写入性能。

非聚簇索引:

独立于表的物理存储方式,可以包含多个索引,查询效率相对于聚簇索引较低,但对插入、更新和删除操作的影响较小。

二者核心区别:数据和索引是否绑定在一起,聚簇索引是绑定在一起的而非聚簇索引是没有绑定在一起的。

5.语法

(1).创建索引

可以使用CREATE INDEX语句或在创建表时定义索引:

sql 复制代码
-- 创建表时添加索引
CREATE TABLE example (
  id INT AUTO_INCREMENT,
  name VARCHAR(100),
  age INT,
  PRIMARY KEY (id),
  UNIQUE KEY unique_name (name),
  INDEX index_age (age)
);

-- 在已有表上添加索引
CREATE INDEX index_name ON example (name);

(2).查看索引

可以使用SHOW INDEX命令查看表中的索引信息:

sql 复制代码
SHOW INDEX FROM example;

(3).删除索引

可以使用DROP INDEX语句删除索引:

sql 复制代码
DROP INDEX index_name ON example;

6.失效的场景:

(1).使用LIKE通配符时

LIKE的查询模式以通配符(如%)开头时,索引会失效,因为MySQL需要对每一行进行全表扫描。

sql 复制代码
-- 索引失效
SELECT * FROM users WHERE name LIKE '%abc';

(2).使用OR条件时

如果OR的任意一边没有使用索引,那么MySQL将放弃使用索引,进行全表扫描。

sql 复制代码
-- 索引失效,如果只有name列有索引
SELECT * FROM users WHERE name = 'Alice' OR age = 25;

(3).对索引列进行函数操作

如果在查询条件中对索引列进行了函数操作或表达式计算,索引会失效。

sql 复制代码
-- 索引失效,因为对索引列进行了函数操作
SELECT * FROM users WHERE LOWER(name) = 'alice';

(4).对索引列进行隐式类型转换

如果索引列的数据类型与查询条件的类型不匹配,MySQL会进行隐式类型转换,从而导致索引失效。

sql 复制代码
-- 索引失效,因为name是VARCHAR类型,'123'是字符串
SELECT * FROM users WHERE name = 123;

(5).使用不等于运算符(!=<>

当使用不等于运算符(!=<>)时,MySQL无法使用索引,因为需要扫描大部分数据行。

sql 复制代码
-- 索引失效
SELECT * FROM users WHERE age != 30;

(6).使用IS NULLIS NOT NULL

对于某些类型的索引,使用IS NULLIS NOT NULL时,索引会失效,因为它们需要扫描所有记录来查找空值或非空值。

sql 复制代码
-- 索引失效
SELECT * FROM users WHERE name IS NULL;

(7) .联合索引未按最左前缀原则使用

联合索引(如(a, b, c))需要按照"最左前缀"原则使用。如果查询条件不从索引的最左边列开始,索引将失效。

sql 复制代码
-- 索引失效,因为没有使用最左前缀a
SELECT * FROM users WHERE b = 2;

(8). 数据分布不均导致的索引失效

如果索引列的数据分布极为不均(如大多数值相同,只有少数不同),MySQL优化器可能会选择放弃使用索引。

解决方法:考虑重新设计索引或调整数据分布

(9).使用%通配符前后都有时

LIKE查询模式前后都有%通配符时,索引也会失效:

sql 复制代码
-- 索引失效
SELECT * FROM users WHERE name LIKE '%abc%';

解决方法:避免这种形式,尽量使用有明确前缀或后缀的模式。

7.优缺点:

优点

  • 加速数据的检索速度,减少查询时间。

  • 在某些情况下,使用索引可以优化排序操作。

  • 可以显著提高系统的性能。
    缺点

  • 索引需要占用物理存储空间。

  • 索引的维护会带来额外的开销(如增删改操作时需要更新索引)。

  • 不适合频繁更新的列上使用索引。

8. 总结:

合理地使用索引可以大大提高MySQL数据库的性能,但需要根据具体的应用场景来选择和管理索引。

相关推荐
十叶知秋33 分钟前
【jmeter】jmeter的线程组功能的详细介绍
数据库·jmeter·性能测试
瓜牛_gn2 小时前
mysql特性
数据库·mysql
奶糖趣多多3 小时前
Redis知识点
数据库·redis·缓存
CoderIsArt4 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
师太,答应老衲吧6 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Yaml47 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
Channing Lewis7 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
追风林8 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker
毕业设计制作和分享9 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
ketil279 小时前
Redis - String 字符串
数据库·redis·缓存