本文为【Mysql索引八股文合集】初版,后续还会进行优化更新,欢迎大家关注交流~
hello hello~ ,这里是绝命Coding——老白~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
💥个人主页:绝命Coding-CSDN博客
💥 所属专栏:后端技术分享
这里将会不定期更新有关后端、前端的内容,希望大家多多点赞关注收藏💖
更多历史精彩文章(篇幅过多,不一一列出):
(简历相关)
求职经验分享(1):一份合格的简历应该如何写?-CSDN博客(推荐)
求职经验分享(2):简历如何优化以及如何应对面试【后端篇】-CSDN博客
(项目亮点相关)
大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(1):Redis篇】-CSDN博客
大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(2)】-CSDN博客
(八股文)
大厂面试官问我:Redis处理点赞,如果瞬时涌入大量用户点赞(千万级),应当如何进行处理?【后端八股文一:Redis点赞八股文合集】_java中redis如何实现点赞-CSDN博客大厂面试官问我:布隆过滤器有不能扩容和删除的缺陷,有没有可以替代的数据结构呢?【后端八股文二:布隆过滤器八股文合集】_布隆过滤器不能扩容-CSDN博客
………
(算法篇)
大厂面试:算法考前必看汇总(全)_大厂面试算法题-CSDN博客
MySQL的索引数据结构
索引是一种建立在特定列上的数据结构,索引的原理是把无序的数据变为有序的查询
- mysql索引的数据结构是树,常用的存储引擎innodb采用的是
B+树
- 非关系型数据库MongoDB使用
B树
作为数据库索引
B-Tree
是最常用的用于索引的数据结构。因为它们是时间复杂度低, 查找、删除、插入操作都可以可以在对数时间内完成。另外一个重要原因存储在B-Tree中的数据是有序的。
索引
- 索引是存储引擎用于提高数据库表的访问速度的一种数据结构
优点:
- 为了提高数据的查询效率
- 加快分组和排序的速度(为排序或者分组的字段加索引)
- 加快表与表之间的连接
缺点
- 建立索引需要占用物理空间
- 会降低表的增删改效率,因为每次增删改,需要动态维护索引,导致增删改时间变长
建立原则
- 最频繁使用的、用以缩小查询范围的字段
- 频繁使用的、需要排序的字段
不适合
- where中用不到的字段
- 表记录较少
- 需要经常增删改
- 参与列计算的列
- 区分度不高的,比如性别男女
(索引检索靠磁盘IO操作,好的索引减少磁盘IO操作次数)
一般来说,索引本身也很大,不可能全部存储在内存中,
一般以文件形式存储在磁盘上,索引检索需要磁盘I/O操作。
判断一种数据结构作为索引的优劣主要是看在查询过程中的磁盘IO渐进复杂度,一个好的索引应该是尽量减少磁盘IO操作次数
索引优化的方法
(1)like语句的前导模糊查询不能使用索引
(2)负向条件查询不能使用索引,有时候考虑优化成in
(3)联合索引最左前缀原则,区分度最高的字段在最左边
(4)不要在索引列上面做任何操作(计算、函数),否则会导致索引失效而转向全表扫描
(5)索引不会包含有NULL值的列,
复合索引中只要有一列含有NULL
值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时,尽量使用not null
约束以及默认值。
(6)如果有order by、group by的场景,请注意利用索引的有序性
例如对于语句 where a=? and b=? order by c
,可以建立联合索引(a,b,c)
。
(7)使用短索引
根据实际文本区分度决定索引长度即可
(8)如果明确知道只有一条结果返回,limit 1 能够提高效率
select * from user where login_name=? limit 1
自己明确知道只有一条结果,但数据库并不知道,明确告诉它,让它主动停止游标移动。
(9)超过三个表最好不要 join
- 需要 join 的字段,数据类型必须一致,多表关联查询时,保证被关联的字段需要有索引。
- 例如:
left join
是由左边决定的,左边的数据一定都有,所以右边是我们的关键点,建立索引要建右边的。当然如果索引在左边,可以用right join
。
深层原因
1. 使用聚合函数
使用了聚合函数后,不再是索引的递增顺序了,因此不能使用索引
优化器的偷懒行为
对于select * from tradelog where id + 1 = 10000这个SQL语句,这个加1操作并不会改变有序性,但是MySQL优化器还是不能用id索引快速定位到9999这一行。所以,需要你在写SQL语句的时候,手动改写成 where id = 10000 -1才可以
2. 涉及数据类型转换
可以看出在mysql中,转换的规则是,字符串和数字做比较的话,是将字符串转换成数字,这个语句会走全表搜索,原因是对于优化器来说,这条sql相当于加了函数
索引的优缺点
(优点:加快速度,排序分组,表与表连接)
(缺点:建立索引占物理空间,维护索引)
优点:(对照需要建立索引的情况)
加快数据查询的速度
为用来排序或者分组的字段添加索引,可以加快分组和排序的速度
加快表与表之间的连接
缺点:
建立索引需要占用物理空间
会降低表的增删改查,因为每次对表记录进行增删查改,需要进行动态维护索引,导致增删改时间变长
索引如何优化
(索引覆盖,前缀索引,联合索引,避免失效和冗余)
注意索引顺序: 复合索引的列顺序很重要,应该将最常用于过滤的列放在前面,以便在查询中能更有效地使用索引。
考虑覆盖索引: 覆盖索引是一种情况,查询的数据可以直接从索引中获取,而不需要访问实际的数据行。这可以减少I/O操作,提升查询性能。
使用复合索引: 复合索引是多个列组合在一起的索引,适用于多个列同时被查询条件使用的情况。
索引的作用
(数据存内存,读取磁盘耗时)
索引就「相当于字典中的目录」,通过索引能快速找到数据的位置,极大提高数据库查询效率
数据是存储在磁盘上的,查询数据时,如果没有索引,会加载所有的数据到内存,依次检索,读取磁盘次数较多。
有了索引,就不需要加载所有的数据,因为B+树的高度一般在24层,最多只需读取24次磁盘,查询速度大大提升
【这里扩展一下 索引的类型以及各自的特点 索引的优缺点】
什么情况需要索引
经常(查询,连接,排序)的字段——对应的优点
经常查询的字段
经常连接的字段,可以加快连接速度
经常需要排序的字段,因为索引已经排好序,可以加快排序查询速度
索引的类型
索引数据结构:
Hash表
(通过hash算法快速定位数据,但不适合范围查询,因为需要每个key都进行一次hash)
二叉树
(查找和修改效率都比较高)
InnoDB引擎中使用的索引是B+Tree
相较于二叉树,B+Tree这种多叉树,更加矮宽,更适合存储在磁盘中。
数据结构的区别
当数据量比较大的时候,索引的大小有可能几个G甚至更多,数据量大的索引能达到亿级别,所以为了减少内存的占用,数据库索引是存储在外部磁盘上的。
当我们利用索引查询的时候,不可能把整个索引全部加载到内存,只能逐一加载每个磁盘页,磁盘页对应索引树的节点。
那么Mysql衡量查询效率的标准就是磁盘IO次数。
索引的底层使用的是什么数据结构?
(B+树和哈希表)
和具体存储引擎的实现有关
MySQL Hash 索引、B+树索引
InnoDB 存储引擎 默认索引实现为 B+ 树索引
hash索引:
通过索引列计算一个哈希码,并且存储在索引中,同时在索引表保存指向每个数据行的指针
B+树索引:
访问速度快
因为不需要全表扫描获取数据,数据分布在各节点中
【这里答两个,然后扩展B+和Hash索引各自的优缺点】
B+树特点
B+树是一个平衡树;
B+树的关键字节点都在叶上;
B+树的叶节点是有序的;
非叶节点不存数据,所以可以存更多的索引;
叶节点用双向链表进行连接,方便范围查询;
节点分裂和合并的时候需要IO较少
有利于磁盘预读和缓存(因为有序存储)
- B+ 树是基于 B 树和叶子节点顺序访问指针进行实现,它具有 B 树的平衡性,并且通过顺序访问指针来提高区间查询的性能。
- 在 B+ 树中,一个节点中的 key 从左到右非递减排列,如果某个指针的左右相邻 key 分别是 key i 和 key i+1,且不为 null,则该指针指向节点的所有 key 大于等于 key i 且小于等于 key i+1。
- 进行查找操作时,首先在根节点进行二分查找,找到一个 key 所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出 key 所对应的 data。
- 插入、删除操作会破坏平衡树的平衡性,因此在插入删除操作之后,需要对树进行一个分裂、合并、旋转等操作来维护平衡性。
内存布局:
- 顺序访问性能好: B+树的内部结构使得在内存中进行顺序访问非常高效。内部节点只包含索引信息,而数据存储在叶子节点上,这意味着从根节点到叶子节点的路径是一个有序的连续序列。
- 缓存友好: B+树的叶子节点构成了一个有序链表,这使得范围查询非常高效。数据库管理系统可以利用缓存预取机制来提前将可能需要的数据加载到内存中,从而减少磁盘访问。
磁盘布局:
- 适应大规模数据: B+树的平衡性质使得树的高度相对较低,能够有效地支持大规模数据的索引。每个节点能够容纳多个键值,降低了索引层次,减少了磁盘访问次数。
- 磁盘预读优势: B+树的内部节点不存储数据,仅存储索引键,因此一个节点的大小通常小于一个数据库页的大小。这使得在磁盘读取时能够读取更多的索引键,从而提高了磁盘预读的效率。
- 范围查询效率: B+树的叶子节点构成有序链表,这使得范围查询非常高效。数据库管理系统可以在磁盘上连续读取叶子节点,从而实现范围查询。
为什么Mysql选择B+树做索引而不是其他的树
(二叉树层次高,读取磁盘次数多,影响性能)
Mysql的数据都是存放在磁盘,因此磁盘IO是Mysql的性能瓶颈
而二叉树,二叉搜索树,二叉平衡树,红黑树 都属于二叉树,
当MySQL表中的数据量比较大时,索引的体积也会很大,树高就会很大,
内存放不下的需要从磁盘读取,树的层次太高的话,
读取磁盘的次数就多了,影响MySQL的使用性能。
为什么Mysql选择B+树做索引而不是B树
考虑的是 IO 对性能的影响
B 树的每个节点都存储数据,而 B+ 树只有叶子节点才存储数据,所以查找相同数据量的情况下,B 树的高度更高,IO 更频繁。
数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。
红黑树不行的原因
(磁盘IO效率、范围查询性能、 缓存效率 、存储效率、插入和删除操作)
红黑树虽然是一种平衡二叉树,但其分支较窄,可能导致在磁盘存储环境下,单次访问获取的数据较少,从而增加了磁盘IO次数。
红黑树在范围查询时可能表现不如B+树。由于红黑树的节点不保存范围信息,范围查询需要在整个树上搜索
红黑树的分支较窄,可能导致磁盘IO更频繁,不太适合利用缓存。
红黑树的每个节点都包含数据和索引信息,这可能导致存储空间的浪费。
红黑树的插入和删除操作相对复杂,可能需要进行节点的旋转和重新平衡
B树不行的原因
(磁盘IO效率、范围查询性能、缓存效率、存储效率)
B 树在磁盘存储环境下的磁盘IO效率相对较低。由于 B 树的每个节点都同时保存了数据和索引信息,这可能导致在磁盘IO时获取的数据较少,增加了磁盘IO次数。
B 树在范围查询时可能表现不如 B+ 树。B 树的内部节点和叶子节点都可能包含数据,因此在范围查询时需要在整个树上进行搜索
与 B+ 树相比,B 树的内部节点可能包含数据,使得它的分支较窄,不太适合利用缓存
B 树的每个节点都同时包含了数据和索引信息,这可能导致存储空间的浪费
B+树最后一层是双向链表还是单向链表
通过双向链表连接叶子节点,B+树在范围查询中具有以下优势:
- 范围查询效率高:由于叶子节点之间有指针连接,可以通过顺序遍历叶子节点获取范围内的数据记录,避免了不必要的磁盘访问和索引的跳转。
- 顺序访问优化:当进行顺序访问时,B+树可以通过双向链表进行高效的顺序遍历,减少磁盘IO次数,提高访问性能。
哈希索引
能以 O(1) 时间进行查找,但是失去了有序性。无法用于排序与分组、只支持精确查找,无法用于部分查找和范围查找。
InnoDB 存储引擎有一个特殊的功能叫“自适应哈希索引”,当某个索引值被使用的非常频繁时,会在 B+ 树索引之上再创建一个哈希索引,这样就让 B+Tree 索引具有哈希索引的一些优点,比如:快速的哈希查找。
覆盖索引
(select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。)
如果一个索引包含了满足查询语句中字段与条件的数据就叫做覆盖索引。具有以下优点:
- 索引通常远小于数据行的大小,只读取索引能大大减少数据访问量。
- 一些存储引擎(例如:MyISAM)在内存中只缓存索引,而数据依赖于操作系统来缓存。因此,只访问索引可以不使用系统调用(通常比较费时)。
- 对于 InnoDB 引擎,若辅助索引能够覆盖查询,则无需访问主索引。
Hash索引和B+树索引的区别?
(Hash索引特点精确查找,本身哈希冲突和无序)
- 哈希索引不支持排序,因为哈希表是无序的。
- 哈希索引不支持范围查找。
- 哈希索引不支持模糊查询及多列索引的最左前缀匹配。
- 因为哈希表中会存在哈希冲突,所以哈希索引的性能是不稳定的,而B+树索引的性能是相对稳定的,每次查询都是从根节点到叶子节点。
索引的分类?
数据结构角度
树 Hash
物理存储角度
聚集 非聚集
逻辑
普通 唯一 主键 联合 全文
普通索引:
最基本的索引,没有任何限制,值可以为空;仅加速查询
唯一索引:
与普通索引类似,不同的是索引列的值必须唯一,但允许有空值;如果是组合索引,则列值必须唯一
唯一索引用于确保某一列或一组列的值在表中是唯一的,但可以包含 NULL 值。与主键索引不同,一张表可以有多个唯一索引。
主键索引:
特殊的唯一索引,一个表只能有一个主键,不允许有空值
组合索引:
多个字段创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用,遵循最左前缀集合
复合索引的顺序很重要,通常将最常用于查询条件的列放在前面。
全文索引:
主要用来查找文本的关键词,而不是直接与索引的值比较
聚簇索引:
表数据按照索引的顺序来存储的
非聚簇:
表数据存储顺序与索引顺序无关
-- 创建主键索引
ALTER TABLE table_name ADD PRIMARY KEY (column_name);
-- 创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column_name);
-- 创建非唯一索引
CREATE INDEX index_name ON table_name (column_name);
范围搜索是否索引生效
索引失效是因为DBMS发现全表扫描比走索引效率更高,因此就放弃了走索引。
然而,如果查询范围涵盖了索引中的大部分数据,数据库优化器可能会选择不使用索引,而是进行全表扫描,以避免频繁的索引访问。
谈谈对聚簇索引的理解
聚集索引和非聚集索引是指物理存储的方式,
InnoDB 的默认数据结构是聚簇索引,MyISAM 是非聚簇索引。
聚簇索引的表索引和数据是通过聚合的方式结合,非聚簇索引的表索引和数据没有聚合。
/
(存储数据的顺序和索引顺序一致)
聚簇索引是对磁盘上实际数据重新组织以按指定的一个或多个列的值排序的算法。
特点是存储数据的顺序和索引顺序一致。一般情况下主键会默认创建聚簇索引,且一张表只允许存在一个聚簇索引。
聚簇索引只能在搜索条件是主键值时才能发挥作用
/
innodb中的b+树就是,将索引和数据保存在同一个b+树中
在innodb中的b+树就是索引和数据不保存在一起
创建
在创建表时,InnoDB 存储引擎会根据不同的场景选择不同的列作为索引:
- 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
- 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key);
- 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key);
其它索引都属于辅助索引(Secondary Index),也被称为二级索引或非聚簇索引。创建的主键索引和二级索引默认使用的是 B+Tree 索引。
聚簇索引和非聚簇索引的区别
(1)顺序、唯一性
聚簇索引的顺序就是数据的物理存储顺序,而对非聚簇索引的解释是:索引顺序与数据物理排列顺序无关
(所以一个表最多只能有一个聚簇索引)
聚簇索引的叶节点就是数据节点。而非聚簇索引的叶节点仍然是索引节点,只不过有一个指针指向对应的数据块。
非聚簇索引
非聚簇索引是普通的索引类型,它将索引和数据分开存储。
(2)查询性能
在聚簇索引上进行查询时,可以直接通过索引找到对应的数据行,无需进行额外的IO操作。
如果非聚簇索引包含了查询所需的所有列,称之为"覆盖索引",可以避免访问实际的数据行
会出现回表:当查询需要获取除了聚簇索引列之外的其他列的值时,需要通过聚簇索引找到对应的行,然后再通过行指针(或称为回行指针)到堆中读取其他列的值。因此,回表操作发生在非聚簇索引上。
(非聚簇索引存储了索引列的值以及指向对应数据行的指针)
(聚簇索引存储了完整的数据行)
(3)重新组织
如果表的聚簇索引需要重新组织(例如,删除大量行后),可能会导致性能下降,因为整个表的物理结构需要重建。
非聚簇索引可以减少插入和更新操作的性能开销,因为它们不需要重组数据页。
一个表里的主键是不是聚集索引呢?
InnoDB 的默认数据结构是聚簇索引,则是,MyISAM 是非聚簇索引。
非聚簇索引查数据的过程
非聚簇索引的叶子节点包含了索引列的值和指向对应数据行的指针
当根据非聚簇索引进行检索时,数据库首先定位到索引的叶子节点,然后根据 RID 找到实际的数据行。
非聚簇索引查数据的过程大致如下:
- 查询条件:当你执行一个查询,使用了非聚簇索引的列作为查询条件时,数据库优化器会决定是否使用该索引来加速查询。
- 定位索引:数据库根据查询条件,在非聚簇索引的 B-Tree 结构中定位到满足条件的叶子节点。
- 获取 RID:在叶子节点,非聚簇索引保存了指向对应数据行的 RID,数据库使用这些 RID 来找到实际的数据行。
- 读取数据:通过获取到的 RID,数据库访问相应的数据页,读取数据行的内容,并返回给查询。
在查询时使用了二级索引,如果查询的数据能在二级索引里查询的到,那么就不需要回表,这个过程就是覆盖索引。如果查询的数据不在二级索引里,就会先检索二级索引,找到对应的叶子节点,获取到主键值后,然后再检索主键索引,就能查询到数据了,这个过程就是回表。
(查询的数据不能在二级索引查到就需要回表)
(非聚簇索引存储了索引列的值以及指向对应数据行的指针)
(聚簇索引存储了完整的数据行)
聚簇索引和非聚簇索引的使用条件
聚簇索引的使用条件:
- 主键索引: 通常,主键索引是聚簇索引。主键是唯一标识表中记录的列,聚簇索引可以帮助高效地定位数据行。
- 频繁范围查询: 如果查询中经常包含范围查询(如区间查询、排序等),聚簇索引可以提供更高的查询性能,因为它决定了数据在磁盘上的物理存储顺序。
- 热点数据: 当一部分数据被频繁地访问,聚簇索引可以将这些热点数据集中存储在一起,减少随机 I/O 操作。
- 插入顺序: 数据的插入顺序和聚簇索引的顺序一致时,插入操作可以更高效,因为数据不需要频繁地移动。
非聚簇索引的使用条件:
- 频繁的查询操作: 非聚簇索引适合频繁的查询操作,包括等值查询、连接操作等。
- 范围查询和排序: 非聚簇索引可以加速范围查询和排序操作,尤其在查询的列不是主键时。
- 覆盖索引: 当查询所需的列已经包含在非聚簇索引中,可以使用覆盖索引来避免对数据表的随机 I/O 访问,提高查询性能。
- 插入和更新操作: 非聚簇索引对插入和更新操作的影响相对较小,因为数据的物理存储顺序与索引无关。
查索引有没有被用过
使用 Explain 命令来查看语句的执行计划
二级索引(看过1)
聚簇索引只能在搜索条件是主键值时才能发挥作用,如果搜索条件中包含的并不是主键列,二级索引就是解决这个问题的
主键索引的 B+Tree 和二级索引的 B+Tree 区别如下:
- 主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里;
- 二级索引的 B+Tree 的叶子节点存放的是主键值,而不是实际数据。
会先检二级索引中的 B+Tree 的索引值(商品编码,product_no),找到对应的叶子节点,然后获取主键值,然后再通过主键索引中的 B+Tree 树查询到对应的叶子节点,然后获取整行数据。这个过程叫「回表」,也就是说要查两个 B+Tree 才能查到数据。
当查询的数据是能在二级索引的 B+Tree 的叶子节点里查询到,这时就不用再查主键索引查
这种在二级索引的 B+Tree 就能查询到结果的过程就叫作「覆盖索引」,也就是只需要查一个 B+Tree 就能找到数据。
索引的设计原则
(这里对应不用索引的情况)
索引列的区分度越高,索引效果越好(比如使用性别)
尽量使用短索引(对较长的字符串进行索引时,应该指定一个较短的前缀长度,因为较小的索引涉及到的磁盘I/O较少,查询速度更快)
索引不是越多越好,每个索引都需要额外的物理空间,维护也需要花费时间
利用最左前缀原则
什么是最左匹配原则
如果 SQL 语句中用到了组合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个组合索引去进行匹配。当遇到范围查询(>
、<
、between
、like
)就会停止匹配,后面的字段不会用到索引。
例子:
对(a,b,c,d)
建立索引,查询条件为a = 1 and b = 2 and c > 3 and d = 4
,那么a、b和c三个字段能用到索引,而d无法使用索引。因为遇到了范围查询。
使用原因
MySQL 建立联合索引的规则是这样的,它会首先根据联合索引中最左边的、也就是第一个字段进行排序,在第一个字段排序的基础上,再对联合索引中后面的第二个字段进行排序,依此类推。
综上,第一个字段是绝对有序的,从第二个字段开始是无序的,这就解释了为什么直接使用第二字段进行条件判断用不到索引了(从第二个字段开始,无序,无法走 B+ Tree 索引)!这也是 MySQL 在联合索引中强调最左前缀匹配原则的原因。
联合索引(A,B,C) select * from table where order by A asc order by B desc order by C asc; 这个语句会走索引吗,为什么
该语句不会走索引。在SQL中,ORDER BY子句中的多个排序条件会按照从左到右的顺序逐个应用。在给定的语句中,首先按A升序排序,然后按B降序排序,最后按C升序排序。
在一个联合索引(A,B,C)中,索引的顺序是按照(A, B, C)的顺序进行排序的。因此,如果查询中的排序顺序与索引的顺序完全匹配,那么索引将被用到。但是在这个例子中,查询中的排序顺序与索引的顺序不完全匹配。
使用In时是否使用索引?
结论:IN肯定会走索引,但是当IN的取值范围较大时会导致索引失效,走全表扫描
场景1:当IN中的取值只有一个主键时
走索引
场景2:扩大IN中的取值范围
此时仍然走了索引,但是效率降低了
场景3:继续扩大IN的取值范围
发现此时已经没有走索引了,而是全表扫描。
如果使用了 not in,则不走索引。
什么情况下索引会失效?即查询不走索引?
对于组合索引,不是使用组合索引最左边的字段,则不会使用索引
%词语%–模糊查询(以%开头的like查询,无法使用索引;非%开头的like查询如abc%,相当于范围查询,会使用索引)
字符串与数字比较不走索引(比如字符串,没有使用引号,可能会因为类型不同发生隐式转换,使索引失效)
查询条件中有 or
索引列参与表达式计算
函数运算
正则表达式
优化器估计使用全表扫描要比使用索引快
/
查询条件,没有索引字段
查询条件使用 or, 选择式过滤条件,导致索引无效
查询条件使用like,且从头部开始模糊匹配,导致索引无效
查询条件不满足复合索引的最左匹配原则,导致索引无效
查询条件,索引列使用了隐式类型转换,导致索引无效
查询条件,索引列使用了聚合函数,导致索引无效
查询条件,索引列使用了算术运算(+、-、…),导致索引无效
查询条件,索引列使用了逻辑运算(!=、<>、is null、 is not null …),导致索引无效
左右关联时,字段类型不一致,导致索引无效
对应的解决方法:
- 没有索引字段:
-
- 在查询中尽量避免没有索引字段的情况。如果没有索引字段,可以考虑优化查询,使用其他方式降低查询的复杂性或减少数据量。
- 使用 OR 条件:
-
- 使用
OR
条件时,通常无法充分利用索引。您可以尝试重构查询,将多个OR
条件拆分成多个查询,然后使用UNION
或UNION ALL
来合并结果。这样可以更有效地使用索引。
- 使用
- 使用 LIKE 进行模糊匹配:
-
- 如果使用
LIKE
进行模糊匹配并且从头部开始匹配,索引也无法充分利用。在这种情况下,可以考虑使用全文搜索引擎(如Elasticsearch)或专门的文本搜索索引(如全文索引)来优化模糊匹配。
- 如果使用
- 不满足复合索引的最左匹配原则:
-
- 复合索引的最左匹配原则要求查询条件按照索引的顺序使用。如果无法满足这个原则,可以考虑创建额外的索引以满足查询需求,或者考虑重构查询以减少索引的依赖。
- 索引列使用了隐式类型转换:
-
- 尽量避免在索引列上使用隐式类型转换。确保查询中的条件和索引的数据类型一致,以便充分利用索引。
- 索引列使用了聚合函数:
-
- 如果需要使用聚合函数,通常无法直接利用普通索引。您可以考虑为聚合查询创建专门的汇总表,并在汇总表上使用索引,以提高性能。
- 索引列使用了算术运算:
-
- 尽量避免在索引列上使用算术运算,因为这会导致无法使用索引。如果需要进行算术运算,可以考虑将结果存储在另一个列中,并在查询中使用该列。
- 索引列使用了逻辑运算:
-
- 类似于算术运算,逻辑运算也会导致索引无效。避免在索引列上使用逻辑运算,考虑存储运算结果在另一个列中,并在查询中使用该列。
- 左右关联时字段类型不一致:
-
- 在左右关联时,确保参与关联的字段具有相同的数据类型。如果类型不一致,可以使用类型转换函数将它们转换为相同的数据类型,以避免索引无效。
什么是前缀索引
在很长的字符列上创建索引,这会造成索引特别大且慢。使用前缀索引可以避免
前缀索引
对文本或者字符串的前几个字符建立索引
这样索引的长度更短,查询速度更快。
创建前缀索引的关键
选择足够长的前缀以保证较高的索引选择性。索引选择性越高查询效率就越高,因为选择性高的索引可以让MySQL在查找时过滤掉更多的数据行。
前缀索引的最好效果是:不重复的索引值(也称为基数cardinality)和数据表的记录总数的比值,越大越好
建立前缀索引的方式:
// email列创建前缀索引
ALTER TABLE table_name ADD KEY(column_name(prefix_length));
Mysql的引擎
MySQL 常见的存储引擎 InnoDB、MyISAM
InnoDB 是在 MySQL 5.5 之后成为默认的 MySQL 存储引擎
B+Tree 索引类型也是 MySQL 存储引擎采用最多的索引类型
InnoDB支持事务和行级锁定的存储引擎
MyISAM
InnoDB 和 MyISAM的区别
MylSAM InnoDB
- 锁 只支持表级 可以支持行级
(底层上看)
- 事务 不支持 支持
(二者存储数据方式的区别,导致MyISAM无法实现行锁,只能支持表锁,因此MyISAM不支持事务)
- 外键 不支持 支持
( 因为在早期数据库设计中,数据库的设计与Excel表的功能差不多,只是用来存数据的) - 全文索引 支持 5.6前不支持
(在涉及全文索引领域的查询效率上MyISAM速度更快高;但是在5.7版本以后的InnoDB支持全文索引了)
对于count 直接存储总行数 不会,按行扫描
(InnoDB不保存表的具体行数)
(如果数据量大,MyISAM 会瞬间返回,而 InnoDB 则会一行行扫描 )
InnoDB表必须有唯一索引(如主键),而Myisam可以没有
(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键)
(总结,mylsam不支持事务,不支持外键,只支持表级锁,对于count 会快点)
InnoDB和MyISAM所使用的索引
两种引擎都是使用B+树。
MyISAM引擎,B+树的数据结构中存储的内容实际上是实际数据的地址值。也就是说它的索引和实际数据是分开的,只不过使用索引指向了实际数据。这种索引的模式被称为非聚集索引。
Innodb引擎的索引的数据结构也是B+树,只不过数据结构中存储的都是实际的数据,这种索引有被称为聚集索引。
【扩展到聚族索引和非聚族索引的区别】
后期新的八股文合集文章会继续分享,感兴趣的小伙伴可以点个关注~
更多精彩内容以及免费资料请关注公众号:绝命Coding