教学视频来源:黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括
索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特点查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高价查找算法,这种数据结构就是索引。
使用索引可以提高查询速度,比如查找年龄是45的用户
注: 上述二叉树索引结构只是一个示意图,并不是真正的索引结构
优点:
提高查询性能:索引可以大大减少查询数据的扫描量,从而提高查询效率。通过使用索引,数据库可以更快地定位和检索所需的数据。
加速排序操作:如果查询中包含排序操作,索引可以加快排序的速度。通过使用索引,数据库可以快速定位并返回排序结果。
提高数据唯一性:可以在索引中定义唯一性约束,确保表中的数据不重复。
支持快速聚合操作:对于包含聚合函数的查询,索引可以提供更快的结果计算和返回。
缺点:
占用存储空间:索引需要占用额外的存储空间。随着索引的增加,数据库的存储需求也会增加。
增加写操作的开销:当对表进行插入、更新和删除操作时,索引也需要进行相应的更新。因此,索引会增加写操作的开销,对性能产生一定的影响。
维护索引需要时间:当表中的数据发生变化时,索引也需要相应地进行维护。这会导致写操作的延迟增加。
不适用于所有情况:对于某些小型表或者数据分布不均匀的表,使用索引可能不会带来明显的性能提升,甚至可能降低查询性能。
MySQL中的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含一下几种:
InnoDB存储引擎使用的是B+tree索引结构。原因是:
在InnoDB存储引擎中,根据索引的存储形式,又可以分为以下两种:
聚集索引选取规则:
创建索引
create [unique | fulltext] index index_name on table_name(index_col_name,...)
查看索引
show index from table_name
删除索引
drop index index_name on table_name
通常主键为主键索引,如果使用主键来查询数据会比使用其他字段查询的速度会更快。如果需要使用其他字段来进行查询时,当数据量过大时,可以通过创建索引来提示查询效率。
注: 当数据量过大时,构建索引也会花费一些时间
我们在执行查询语句时,可以在查询语句前面加上explain
关键字,来查看该查询语句使用了哪些索引
最左前缀法则
如果索引了多列(联合索引,由多个列组成的索引),要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。
如果查询条件没有按照索引的最左前缀顺序提供,MySQL将无法充分利用索引,可能会导致全表扫描或部分索引扫描,从而影响查询性能。
如果跳过某一列,索引将部分失效(后面的字段索引失效)
例如,如果您创建了一个复合索引 (col1, col2, col3):
范围查询
联合索引中,出现范围查询(大于、小于),范围查询右侧列的索引失效。大于等于这种的会生效
例如下面这条sql,后面的 and sex = '男'
是不会生效
select * from student where profession = '软件工程' and age > 23 and sex = '男'
索引列运算
不要在索引列上进行运算操作,索引将失效。
字符串
字符串类型字段使用时,不加引号,索引将失效。这里指的是字符串类型的数字
模糊查询
如果是头部模糊匹配,索引失效,比如:
explain select * from student where name like '%四'
or连接的条件
用or
分割的条件,如果or
前的条件中有列索引,而后面的列中没有索引,那么涉及的索引都不会被用到
数据分布影响
在执行查询时,MySQL会进行评估,如果使用索引比全表扫描更慢,则不适用索引
当字段类型为字符串时,有时候需要索引很长的字符串,这会让索引变得很大,查询时浪费大量的磁盘IO,影响查询效率。
此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法
// index_name:索引名称 table_name:表名 column:列 n:指定几个字符
create index index_name on table_name(column(n))
前缀长度
可以根据索引的选择性来决定,而选择性是指不重复的索引值和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
计算方式示例
select count(distinct name) / count(*) from student;
select count(distinct substring(name,1,10)) / count(*) from student;
通过修改截取的字符串长度来计算几个字符比较合适后就可以创建前缀索引了,比如:create index index_name_3 on student(name(3))
在业务场景中,如果存在多个查询条件,考虑针对查询字段建立索引时,建议建立联合索引,而非单例索引。