MySql索引
索引概述
索引是高效获取数据的数据结构;
索引(index)是帮助MySQ高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些
数据结构以某种方式引用(指向)数据, 这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
优点:提高数据检索的效率,降低数据库的IO成本。通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消
耗。
缺点:索引列也是要占用密间的。索引大大提高了查询效率,同时却也降低更新表的速度,如对表进行INSERT、UPDATE、DELETE时,效率降低(如果索引参与修改,需要重新构建索引结构)。
总结:空间换时间。
索引结构
常见的索引结构
(1)B+树:最常见的索引类型,大部分引擎都支持 B+树索引
(2)Hash:底层数据结构是用哈希表实现的,只有精确匹配索引列的查询才有效,不支持范围查询
(3)R-tree(空间索引):空间索引是MVISAM引擎的一个特殊索引类型,主要用于地理空间数据类型,通常使用较少
(4)Full-text(全文索引):是一种通过建立倒排索引,快速匹配文档的方式。类似于Lucene,Solr,ES
可用作索引的结构分析
(1)二叉树:
最坏情况:所有列成一排,形成链表,如下:
二叉树缺点:顺序插入时,会形成一个链表,查询性能大大降低。大数据量情况下,层级较深,检索速度慢。
(2)红黑树
缺点:本质也是二叉树,大数据量情况下,层级较深,检索速度慢
(3)B树(多路平衡查找树)
当某一节点的元素数量等于最大度数时,中间的元素向上分裂,连接左右两边。
B树缺点:
(4)B+树
和B树一样,也会中部分裂,但是元素不会真的上去,而是给上面复制一份,形成新的节点。
所有元素都存储在叶子节点,上面的部分存储的仅仅是索引。
MySQL索引数据结构对经典的B+Tree进行了优化。在原B+Tree的基础上,增加一个指向相邻叶子节点的链表指针,就形成了带有顺序指针的B+Tree,提高区间访问的性能。
(5)Hash
哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。
如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决。
Hash索引特点
1.Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,<,
2.无法利用索引完成排序操作
3.查询效率高,通常只需要一次检索就可以了,效率通常要高于B+tree索引
在MySQL中,支持hash索引的是Memory引擎,而innoDB中具有自适应hash功能,hash索引是存储引擎根据B+Tree索引在指定条件下自动构建的。
innoDB中具有自适应hash功能:InnoDB 提供了一种称为“自适应哈希索引”的优化机制。它会自动为频繁访问的索引页(B+树叶子节点)构建哈希索引,以加速等值查询。自适应哈希索引是 InnoDB 内部自动管理的,用户无法手动创建或控制。
它适用于某些特定的查询场景,但并不适用于范围查询或排序操作。
采用B+树作为索引的原因和比较
(1)相对于二叉树,层级更少,搜索效率高
(2)对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的
高度,导致性能降低;
(3)相对Hash索引,B+tree支持范围匹配及排序操作,
索引分类
(1)主键索引:针对于表中主键创建的索引,只能有一个。PRIMARY
(2)唯一索引:避免同一个表中某数据列中的值重复。UNIQUE
(3)常规索引:快速定位特定数据
(4)全文索引:查找的是文本中的关键词。FULLTEXT
(5)聚集索引:将row数据存储与索引放到了一块,索引结构的叶子节点保存了行数据。索引是主键,内容存的是row数据。必须有,有且只有一个。
(6)二级索引:将row数据与索引分开存储,索引结构的叶子节点关联的是对应的主键。索引是自定义的字段,内容存的是主键。
主键索引和聚集索引的关系:如果表定义了主键,那么主键索引就是聚集索引;没有定义主键,InnoDB 会选择一个唯一的非空索引(unique not null)作为聚集索引。如果没有这样的索引,InnoDB 会隐式创建一个隐藏的 ROWID 作为聚集索引。
索引语法
创建索引:create index xxx on xxx(xxx)
展示索引:show index xx from xxx
删除索引:drop index xx on xxx
SQL性能分析工具
查看执行频次:show global status like 'Com_______'(7个横线)
慢查询日志:略
profile:show profiles 能够在做SQL优化时帮助我们了解时间都耗费到哪里去了
SELECT @@have profiling
默认profiling是关闭的,可以通过set语句在session/global级别开启profiling:
SET profiling =1;
profile详情:执行一系列的业务SQL的操作,然后通过如下指令查看指令的执行耗时
#查看每一条SOL的耗时基本情况
show profiles;
#查看指定query id的SQL语句各个阶段的耗时情况
show profile for query query_id,
#查看指定query id的SQL语句CPU的使用情况
show profile cpu for query query_ id;
explain执行计划:
id:select查询的序列号,表示查询中执行select子句或者是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。
select type:表示 SELECT的类型,常见的取值有 SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(SELECT/WHERE之后包含了子查询)等
type:表示连接类型,性能由好到差的连接类型为NLL、system、const、eg ref、ref、range、index、all 。
possible key:可能使用的索引
Key:实际使用的索引,如果为NULL,则没有使用索引。
Key len:表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好
rows:MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。
filtered:表示返回结果的行数占需读取行数的百分比,filtered 的值越大越好。
索引使用原则
联合索引中的最左前缀法则:如果索引了多列联合索引,要遵守最左前缀法则。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效
索引失效
(1)模糊查询:如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
(2)如果MySQL评估使用索引比全表更慢,则不使用索引
(3)用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。只有在两个条件都有索引时才会生效。
(4)字符串类型字段使用时,不加引号,索引将失效
SQL提示
SOL提示,是优化数据库的一个重要手段,简单来说,就是在SOL语句中加入一些人为的提示来达到优化操作的目的。
use和ignore只是知道作用,真正用什么还是取决于mysql
use index:
explain select * from tb user use index(idx user pro) where profession ='软件工程'
ignore index:
explain select * from tb user ignore index(idx user pro) where profession ='软件工程'
force index:
explain select * from tb user force index(idx user pro) where profession ='软件工程'
覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select *
也就是说,对加索引的字段最好也是查询的字段,另外可能最多也就查询一个主键,这样的话就通过二级索引就可以查到了。
前缀索引
当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘IO,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法
create index idx xxxx on table name(column(n));
前缀长度
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高,唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
select count(distinct email)/ count(*) from tb user
select count(distinct substring(email,1,5))/ count(*)from tb user ;
也就是说,最好截取少一点,并且选择性接近于1。当匹配后,在进行全文匹配。
单列/联合索引
单列索引:即一个索引只包含单个列。
联合索引:即一个索引包含了多个列。
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。
当使用多条件联合查询时,MySQL优化器会评估哪个字段的索引效率更高,会选择该索引完成本次查询。
索引设计原则
1.针对于数据量较大,且查询比较频繁的表建立索引。
2.针对于常作为查询条件(where)、排序(orderby)、分组(group by)操作的字段建立索引。
3.尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。
4.如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。
5.尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。
6.要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。
7.如果索引列不能存储NULL值,请在创建表时使用NOTNULL约束它。当优化器知道每是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)