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 NULL
或IS NOT NULL
对于某些类型的索引,使用IS NULL
或IS 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数据库的性能,但需要根据具体的应用场景来选择和管理索引。