MySQL数据库中的索引(各种索引的区别、索引索引失效原因、索引优化、面试中常问的问题详解)

索引模块


1.为什么要使用索引?
  • 当查询数据量较小的表时(如只有几十行数据的表),全表扫面的速度依旧很快,当访问数据库较大的表时全表扫面的效率会十分低下,所以要使用索引的方式。

  • 避免全表扫描,快速查询数据:设计思想类似于字典

2.什么样的信息能成为索引?
  • 主键、唯一键、普通键等(具有较好的区分度的字段都可以)

3.索引的数据结构

二叉查找树(不适合作为索引)

特点:左子树小于右子树

查找方式:二分查找

时间复杂度:平均 O ( log n ) 最坏情况下:O ( n ),会变成线性的二叉树

缺陷:

1.最坏情况下变成线性二叉树,时间复杂度变成O ( n )

2.在树查找时,每读取一次数据就会发生一次I/O,二叉树的深度越深,I/O的次数越多,而二叉树每个节点最多有两个孩子,若用二叉树作为索引,树的深度会很深,I/O性能消耗太大。

优化思考:把树的节点的数目增加,形成一个多叉树

B树(不适合作为索引)

定义:

  • 根节点至少包括两个孩子

  • 树中每个节点最多含有m个孩子(m >= 2)

  • 除根节点和叶子节点外,其他每个节点至少有 ceil(m/2) 个孩子,ceil为向上取值

  • 所有叶子节点都位于同一层

  • 假设每个非终端结点中包含有n个关键字信息,其中

    a)Ki(i=1…n)为关键字,且关键字按顺序升序排序K(i-1)<Ki

    说明:如第二行每个节点左边的必须小于右边的(如:8 < 12)

    b)关键字的个数n必须满足:[ceil(m/2)-1]<=n<=m-1

    说明:关键字的个数永远比它孩子的数量少一个(如第二行,每个节点关键字个数为2,孩子数为三)

    c)非叶子结点的指针:P[1],P[2]……P[M];其中P[1]指向关键字小于K[1]的子树,P[M]
    指向关键字大于K[M-1]的子树,其它Pi]指向关键字属于(K[i-1],Ki])的子树

    说明:每个关键字的最左边的孩子节点的大小都小于此关键字(如:8的孩子节点3,5小于8);每个关键字的最右边的孩子节点都大于此关键字所在节点所有的数(如:12的孩子节点13和15大于12,8);关键字子节点中间数的大小在夫父节点所在的大小范围内(如:9,10在8-12的范围内)

时间复杂度:O ( log n )

Q:若插入数据打乱的树的现有结构,树会进行什么变化?

  • 通过合并、分裂、上移、下移节点来维持B树的约束
B+树(常用索引):

定义:基本与B树相同,但是要求

  • 非叶子节点的子树指针与关键字个数相同
  • 非叶子节点的字数指针P[i],指向关键字值( K [i] , K [i+1] )的子树
    • 说明:如P2指针指向的子树中所有的值必须小于P3子树的所有树的值
  • 非叶子节点仅用来索引(这样能存更多的关键字),数据都保存在叶子节点中
  • 所有叶子节点均有一个链指针指向下一个叶子节点(这样做是为了支持范围统计)
    • 说明:如搜索大于等于10的数,直接走到P2节点下进行搜索然后直接使用链指针继续横向跨子树进行往后搜索,不需要回到P2节点再从P3…下一个P1…P2…P3这样一步一步搜索,提高效率。

Q:为什么B+树比B树更适合做索引(MySQL)

  • 磁盘读写代价低:非叶子节点仅用来索引(这样能存更多的关键字),数据都保存在叶子节点中,相对与B树能存放更多的关键字,磁盘读写代价低(树的深度低,读的关键字更多)

  • B+树的查询效率更加稳定,是稳定的O ( log n )

  • B+树更有利于对数据库的扫描,如进行范围查询,在普通查询时性能也更好

Hash(哈希索引,非主流索引)

特点:类似于HashMap

查询效率极高(比B+树还高),但不能作为主流索引

缺点:

  • 只能用于对等值的查询,不能实现对范围的查询,即:仅能满足“=",“IN"不能使用范围查询

    • 因为Hash是通过hash算法计算出的hash值进行查找,因为计算过后的hash值的大小顺序不能保证和原数据一致(还可能会有hash冲突),所以不能使用范围查找
  • 不能用于对数据的排序操作(也是因为hash算法的原因)

  • 对与组合索引,不能使用部分索引查询

    • 因为计算组合索引hash值时,是对整个组合索引一起做hash运算,计算结果不能拆分(即,abc组合索引,使用ab无法命中索引)
  • 不能避免全表扫面

  • 不稳定:遇到大量Hash值相等的情况,性能并不一定比B+树高(甚至有可能变成线性结构–链表)

BitMap(位图索引,Oracle数据库支持)

Oracle数据库支持,MySQL数据库不支持

特点:数据结构类似于B+树,速度快

缺陷:锁的粒度较大,在发生CRUD时,为防止别的线程修改数据,会加锁(因为位图与行有严格的关系)

适用场景:

适用于统计情况较多的场景,不适应与高并发的场景


4.索引类型

Hash索引:类似于HashMap,特点前面有
普通索引:普通字段使用的索引,通常为B+ Tree结构
唯一索引:字段或组合字段唯一的索引
主键索引:主键字段所使用的索引,非空且唯一性,通常为密集索引
联合索引:多个字段组合一起的索引,使用时要注意保证最左匹配原则
全文索引:全文索引,目前只有MyISAM引擎支持,可以在CHAR、VARCHAR或者TEXT类型的列上创建
覆盖索引:SQL只需要通过索引就可以返回查询所需要的数据(select和where字段上都有索引),而不必通过二级索引查到主键之后再去查询数据(不需要再进行回表操作)

5.密集索引和稀疏索引

聚集索引

(1):聚集索引就是以主键创建的索引

(2):每个表只能有一个聚簇索引,因为一个表中的记录只能以一种物理顺序存放,实际的数据页只能按照一颗 B+ 树进行排序

(3):表记录的排列顺序和与索引的排列顺序一致

(4):聚集索引存储记录是物理上连续存在

(5):聚簇索引主键的插入速度要比非聚簇索引主键的插入速度慢很多

(7):更新聚集索引列的代价很高,因为会强制innodb将每个被更新的行移动到新的位置

非聚集索引

(1):除了主键以外的索引

(2):聚集索引的叶节点就是数据节点,而非聚簇索引的叶节点仍然是索引节点,并保留一个链接指向对应数据块

(3):聚簇索引适合排序,非聚簇索引不适合用在排序的场合

(4):聚集索引存储记录是物理上连续存在,非聚集索引是逻辑上的连续。

Q:使用聚集索引为什么查询速度会变快?

  • 使用聚簇索引找到包含第一个值的行后,便可以确保包含后续索引值的行在物理相邻

Q:建立聚集索引有什么需要注意的地方吗?

  • 在聚簇索引中不要包含经常修改的列,因为码值修改后,数据行必须移动到新的位置,索引此时会重排,会造成很大的资源浪费

Q:密集索引和稀疏索引的区别?

  • 密集索引文件中的每个搜索码值都对应一个索引值(也就是说,密集索引的索引列中包含数据,可以直接拿到,不需要回表操作,通常为主键索引)

  • 稀疏索引文件只为索引码的某些值建立索引项(部分索引列中包含数据,通常需要回表操作)

  • 聚簇索引适合排序,非聚簇索引不适合用在排序的场合,因为聚簇索引叶节点本身就是索引和数据按相同顺序放置在一起,索引序即是数据序,数据序即是索引序,所以很快。非聚簇索引叶节点是保留了一个指向数据的指针,索引本身当然是排序的,但是数据并未排序,数据查询的时候需要消耗额外更多的I/O,所以较慢

Q:非聚集索引最多可以有多少个?

  • 每个表你最多可以建立249个非聚簇索引。但是需要消耗大量的硬盘空间和内存
6.联合索引
  • 如某个表中建有a,b,c三个字段组成的联合索引,同时使用abc三个字段时会命中索引,使用abc,ab,a,都会命中索引,使用bc,ac,b…都无法命中索引

最左匹配原则:

  • 范围查询在使用联合索引时,MySQL会一直从左向右匹配,直到遇到范围查询(> , < , between ,like)就停止匹配,相当于遇到了断点,不走索引了。

  • 比如:a = 3 and b = 4 and c > 5 and d = 6 如果建立的是(a,b,c,d)顺序的联合索引,d是用不到索引的,如果建立(a,b,d,c)的索引则可以用到索引;

  • = 和 in是可以乱序的,比如a = 1 and b = 2 and c = 3建立(a,b,c)索引,a,b,c的顺序可以是任意的,因为MySQL的查询优化器会自动优化识别的形式(通常以最左匹配原则优化)。

联合索引的最左匹配原则的成因:

  • 联合索引后面的字段是在前面索引的基础上形成的,在进行查询时,后面的索引要根据前面索引才能进行有效的查询。

7.为什么索引会失效?

(1):条件是or,如果还想让or条件生效,给or每个字段加个索引

(2):like开头%

(3):如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不会使用索引

(4):where中索引列使用了函数或有运算

  • 其他情况欢迎大家留言补充

8.数据库事务及隔离级别 详细描述请点击

数据库事务特点

ACID: 原子性,一致性,隔离性,永久性

Q:数据库事务说是如何实现的?

(1):通过预写日志方式实现的,redo和undo机制是数据库实现事务的基础

(2):redo日志用来在断电/数据库崩溃等状况发生时重演一次刷数据的过程,把redo日志里的数据刷到数据库里,保证了事务 的持久性(Durability)

(3):undo日志是在事务执行失败的时候撤销对数据库的操作,保证了事务的原子性

Q:数据库事务隔离级别?

(1):读未提交read-uncommitted-- 脏,不可重复读–幻读 A读取了B未提交的事务,B回滚,A 出现脏读;

(2):不可重复读read-committed-- 不可重复读–幻读 A只能读B已提交的事务,但是A还没结束,B又更新数据隐式提交,然后A又读了一次出现不可重复读;

(3):可重复读repeatable-read<默认>-- 幻读 事务开启,不允许其他事务的UPDATE修改操作 A读取B已提交的事务,然而B在该表插入新的行,之后A在读取的时候多出一行,出现幻读;

(4):串行化serializable–

事务相关详细描述请点击


关于索引的其他面试题

Q:索引是建立的越多越好吗?

  • 数据量小的表不需要建立索引,建立会增加额外的索引开销
  • 数据变更需要维护索引,因此更多的索引意味着更多的维护成本
  • 更多的索引也需要更多的空间

Q:InnoDB 表对主键生成策略是什么样的?

  • 优先使用用户自定义主键作为主键,如果用户没有定义主键,则选取一个Unique键作为主键,如果表中连Unique键都没有定义的话,则InnoDB会为表默认添加一个名为row_id隐藏列作为主键。

Q:数据库索引优缺点

(1):需要查询,排序,分组和联合操作的字段适合建立索引
(2):索引多,数据更新表越慢,尽量使用字段值不重复比例大的字段作为索引,联合索引比多个独立索引效率高
(3):对数据进行频繁查询进建立索引,如果要频繁更改数据不建议使用索引
(4):当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。

Q:索引的底层实现是B+树,为何不采用红黑树,B树?

(1):B+Tree非叶子节点只存储键值信息,降低B+Tree的高度,所有叶子节点之间都有一个链指针,数据记录都存放在叶子节点中

(2):红黑树这种结构,高度明显要深的多,效率明显比B-Tree差很多

(3):B+树也存在劣势,由于键会重复出现,因此会占用更多的空间。但是与带来的性能优势相比,空间劣势往往可以接受,因此B+树的在数据库中的使用比B树更加广泛


PS:欢迎大家留言补充和指正

Spring中七种事务的传播特性

(1)Propagation.REQUIRED<默认> 如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。

(2)Propagation.SUPPORTS 如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。

(3)Propagation.MANDATORY 如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。

(4)Propagation.REQUIRES_NEW 重新创建一个新的事务,如果当前存在事务,延缓当前的事务。

(5)Propagation.NOT_SUPPORTED 以非事务的方式运行,如果当前存在事务,暂停当前的事务。

(6)Propagation.NEVER 以非事务的方式运行,如果当前存在事务,则抛出异常。

(7)Propagation.NESTED 如果没有,就新建一个事务;如果有,就在当前事务中嵌套其他事务。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《海量数据库解决方案》将整体内容分为两部分: 第1部分以影响数据读取效率的所有要素为类别,对其各自的概念、原理、 特征、应用准则,以及表的结构特征、多样化的索引类型、优化器的内部作用、优化器为各种结果制定的执行计划予以详细说明,并以对优化器的正确理解为基础,提出对执行计划和执行速度产生最大影响的索引构建战略方案; 第2部分主要介绍提高数据读取效率的具体战略方案,在这部分介绍与数据读取效率相关的局部范围扫描的原理和具体应用方法,以及对被认为是提高数据库使用效率基础的表连接的所有类型予以详细说明。   《海量数据库解决方案》系列丛书深受广大读者的喜爱已经长达10年之久,在被誉为“圣经”的同时,它已经变成了数据库用户不可或缺的必读书籍。作者竭力探求能够让it工作者在实际工作轻松应用并掌控的巧妙方法,提供事半功倍的海量数据库解决之道。   《海量数据库解决方案》适合数据库开发人员和数据库管理员等阅读。 目录: 第1部分 影响数据读取的因素 第1章 数据的存储结构和特征1 1.1 表和索引分离型5 1.1.1 堆表的结构5 1.1.2 聚簇因子(cluster factor)10 1.1.3 影响读取的因素13 1.1.3.1 大范围数据读取的处理方案14 1.1.3.2 提高聚簇因子的手段17 1.2 索引组织表(index-organized table)19 1.2.1 堆表和索引组织表的比较19 1.2.2 索引组织表的结构和特征20 1.2.3 逻辑rowid和物理猜(physical guess)22 1.2.4 溢出区(overflow area)24 1.2.5 索引组织表的创建25 1.3 聚簇表26 1.3.1 聚簇表的概念27 1.3.2 单表聚簇29 1.3.3 复合表聚簇31 1.3.4 聚簇表的代价34 1.3.5 哈希聚簇39 .第2章 索引的类型和特征43 2.1 b-tree 索引44 2.1.1 b-tree 索引的结构44 2.1.2 b-tree 索引的应用47 2.1.3 反向键索引52 2.2 位图索引53 2.2.1 位图索引的形成背景54 2.2.2 位图索引的结构和特征55 2.2.3 位图索引的读取57 2.3 基于自定义的函数索引60 2.3.1 基于自定义的函数索引的概念和结构60 2.3.2 基于自定义函数索引的约束61 2.3.3 基于自定义函数索引的灵活运用64 第3章 sql的执行计划(explain plan)74 3.1 sql和优化器75 3.1.1 优化器的作用和人的作用77 3.1.2 优化器的类型80 3.1.2.1 基于规则的优化器82 3.1.2.2 基于成本的优化器86 3.1.2.3 优化器目标的选择93 3.1.2.4 执行计划的固定化方案97 3.1.2.5 优化器的局限103 3.1.3 优化器的最优化步骤106 3.1.4 查询语句的转换112 3.1.4.1 传递性规则113 3.1.4.2 视图合并(view merging)116 3.1.4.3 查看用户定义的绑定变量122 3.1.5 开发者的作用123 3.2 执行计划的类型126 3.2.1 扫描的基本类型126 3.2.1.1 全表扫描127 3.2.1.2 rowid扫描132 3.2.1.3 索引扫描133 3.2.1.4 b-tree聚簇读取(cluster access)138 3.2.1.5 哈希聚簇读取(hash cluster access)139 3.2.1.6 采样表扫描(sample table scan)140 3.2.2 表连接的执行计划143 3.2.2.1 嵌套循环连接(nested loops join)143 3.2.2.2 排序合并连接(sort merge join)146 3.2.2.3 哈希连接(hash join)148 3.2.2.4 半连接(semi join)149 3.2.2.5 笛卡儿连接151 3.2.2.6 外连接(outer join)154 3.2.2.7 索引连接159 3.2.3 其他运算方式的执行计划161 3.2.3.1 in-list迭代执行计划162 3.2.3.2 连锁执行计划163 3.2.3.3 远程执行计划165 3.2.3.4 排序操作执行计划168 3.2.3.5 集合操作执行计划171 3.2.3.6 count(stopkey)执行计划174 3.2.4 位图(bitmap)执行计划175 3.2.4.1 各种条件运算符的位图执行计划176 3.2.4.2 子查询执行计划182 3.2.4.3 与b-tree索引相结合的执行计划184 3.2.5 其他特殊处理的执行计划185 3.2.5.1 递归展开(recursive implosion)执行计划186 3.2.5.2 修改子查询执行计划191 3.2.5.3 特殊类型的执行计划193 3.3 执行计划的控制203 3.3.1 提示的活用准则204 3.3.2 使用提示实现最优化目标206 3.3.3 使用提示改变表连接顺序207 3.3.4 表连接方式选择过程提示的使用208 3.3.5 并行操作提示的使用209 3.3.6 数据读取方法选择提示的使用211 3.3.7 查询转换(query transformation)过程提示的使用214 3.3.8 其他提示216 第4章 构建索引的战略方案221 4.1 索引的选定准则222 4.1.1 不同类型表的索引应用准则223 4.1.2 离散度和损益分界点227 4.1.3 索引合并和组合索引的比较229 4.1.4 组合索引的特征232 4.1.5 组合索引列序的决定准则239 4.1.6 索引选定步骤242 4.2 决定聚簇类型的准则263 4.2.1 全局性聚簇263 4.2.2 局部性聚簇265 4.2.3 单表聚簇266 4.2.4 单位聚簇大小的决定267 4.2.5 确保聚簇被使用的措施270 第2部分 最优化数据读取方案 第5章 局部范围扫描(partial range scan)274 5.1 局部范围扫描的概念276 5.2 局部范围扫描的应用原则281 5.2.1 局部范围扫描的条件281 5.2.2 不同优化器模式下的局部范围扫描284 5.3 提高局部范围扫描执行速度的原理285 5.4 向局部范围扫描引导的方法289 5.4.1 利用访问路径实现对sort的代替289 5.4.2 只使用索引的局部范围扫描292 5.4.3 min、max 的处理293 5.4.4 filter型局部范围扫描298 5.4.5 rownum的灵活运用300 5.4.6 利用嵌套视图的局部范围扫描306 5.4.7 利用函数的局部范围扫描308 5.4.8 利用查询语句二元化特性的局部范围扫描316 5.4.9 web留言板的局部范围扫描318 第6章 表连接的最优化方案336 6.1 join和loop query的比较339 6.1.1 全部范围扫描方式下的比较341 6.1.2 局部范围扫描方式下的比较349 6.2 连接条件状态对表连接的影响351 6.2.1 连接条件正常353 6.2.2 连接条件一边异常358 6.2.3 连接条件两边异常361 6.3 各种表连接方式的特征及活用方案365 6.3.1 嵌套循环连接366 6.3.1.1 嵌套循环连接的基本概念367 6.3.1.2 嵌套循环连接顺序的决定370 6.3.2 排序合并连接379 6.3.3 嵌套循环连接和排序合并连接的比较383 6.3.4 哈希连接(hash join)387 6.3.4.1 in-memory哈希连接392 6.3.4.2 延迟哈希连接395 6.3.5 半连接(semi join)398 6.3.5.1 半连接的概念和特征399 6.3.5.2 半连接的执行计划401 6.3.6 星型(star)连接417 6.3.7 星变形(star transformation)连接425 6.3.8 位图连接索引436

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值