数据库索引学习

一、索引介绍

数据库索引调优是一项技术活,不能仅仅靠理论,因为实际情况千变万化,而且各种数据库本身存在很复杂的机制,如查询优化策略和各种引擎的实现等。但同时这些理论是索引调优的基础,只有在明白理论的基础上,才能对调优策略进行合理推断并了解其背后的机制,然后结合实践中不断的实验和摸索。

索引其实就是在数据库存储数据之外,还维护着另外的满足某种查询算法的数据结构,这些数据结构再以某种方式指向真实的存储数据,然后在现有的数据结构上实现快速查询。(找了张很不错的二叉树的图来理解索引,现在大多的索引都是B+树的结构,基本上没有使用二叉树的)。



二、数据库操作时间占用都在IO操作上

索引本身也很大,不可能全部存储在内存中,往往以索引文件的形式存储在磁盘上。所以索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高出好多好多,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。而B+树结构在实际的应用中刚好满足减少物理I/O操作的要求,来胜任索引结构再合适不过了(下面介绍)。


三、随机IO、顺序IO


     数据库查询大部分时间都消耗在了I/O上,而内存I/O要比物理I/O快的多,所以 一次查询操作物理I/O的次数很大程度决定了查询的最终时间。同时物理I/O的种类又分了 顺序、随机I/O, 顺序和随机,是指本次IO给出的初始扇区地址,和上一次IO的结束扇区地址,是不是完全连续的,或者相隔不多的,如果是,则本次IO应该算是一个连续IO,如果相差太大,则算一次随机IO。连续IO,因为本次初始扇区和上次结束扇区相隔很近,则磁头几乎不用换道或换道时间极短;如果相差太大,则磁头需要很长的换道时间,如果随机IO很多,导致磁头不停换道,效率大大降底。

    随机访问的特点是每次IO请求的数据在磁盘上的位置跨度很大(如:分布在不同的扇区),因此N个非常小的IO请求会以N次IO请求才能获取到相应的数据。

    顺序访问的特点跟随机访问相反,它请求的数据在磁盘的位置是连续的。当系统发起N个非常小的IO请求(如:1K)时,因为一次IO是有代价的,系统会取完整的一块数据(如4K、8K),所以当第一次IO完成时,后续IO请求的数据可能已经有了。这样可以减少IO请求的次数。

    随机访问的特点是每次IO请求的数据在磁盘上的位置跨度很大(如:分布在不同的扇区),因此N个非常小的IO请求会以N次IO请求才能获取到相应的数据。

    顺序访问的特点跟随机访问相反,它请求的数据在磁盘的位置是连续的。当系统发起N个非常小的IO请求(如:1K)时,因为一次IO是有代价的,系统会取完整的一块数据(如4K、8K),所以当第一次IO完成时,后续IO请求的数据可能已经有了。这样可以减少IO请求的次数。


四、文件系统和数据库系统中常用的B+ 树结构

在学校时候理解数据库中的查询就认为是一般的顺序查找,现在再回想这种复杂度为O(n)的算法在数据量很大的情况下简直不敢想想,那么多牛逼的查询算法像二分查找、二叉树查找等 在实际的应用上还真没有好好琢磨过。找了些对比B-Tree、B+Tree结构的资料(下图很好诠释了两种结构的区别)。


1、B-Tree、B+Tree主要区别:
    B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。


2、B+ 树的优点在于:

  • B+树在非叶子节点上不存储data,只存储key,因此在加载到内存中时能够存放更多的key;
  • 非叶子节点特别小,出度大的情况下非叶子节点少,可以完全加载到内存中减少 IO次数; 
  • 数据key值存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率。
  • B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索,可以被连续加载;
  • 而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好;
  • 但是B树也有优点,其优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速;



五、组合索引使用场景

常索引有 唯一索引、主键索引、聚集索引,有时候为了了更多的提高mysql效率可建立组合索引,遵循“最左前缀“原则。最左前缀:顾名思义,就是最左优先。例如,对于表title(id,no,name,age)我们创建了以三个字段的组合多列索引(no,name,age),相当于创建了(no)单列索引,(name,fname)组合索引以及(no,name,age)组合索引。

  其他的不多说了,这次主要是对组合索引的学习,下面列出组合索引“最左前缀”的场景 (就以上表title为例、通过查看执行计划是否走了索引):

1、可以走索引的全列匹配

  • 当查询条件 where no=n and name=b and age =20  或者 where no=n  and  name=b  或者where no=n 都可以走进索引;
  • 项mysql查询优化器会自动调整where子句的条件顺序以使用适合的索引,所以把条件顺序做下调整不会影响结果 如:where age=20  and  name=b  and  no=n 同样可以走到索引;
  • 在条件中使用“in”语法同样可以走到索引;


2、最左前缀,中间的一个条件未提供

如 where no = n  and age = 20  少了索引中间列 name ,这时候只用到了索引的第一列no ,后面age虽然也在索引中,由于缺少name列 无法和左前缀连接;


3、查询条件没有指明 索引第一列 

     如果少了索引的第一列no  如:where name = ‘jeck’ and age = 20 这样不匹配最左前缀,就无法走索引了。


4、索引字段中用到了 %的模糊匹配语法

     如果在某列中使用了 % 模糊匹配,要看%的位置判断是否能走到索引, %在字符串的最后则可以使用索引 ,如:
where  no = 1  and name like  'luc%’
; 但是,如果%在前面就不行  如:where no = 1 and name like ‘%cy’ ;


5、范围查找 

     如果在sql中用到了 < 、 >的范围查找 ,且只有一个范围列的 就可以走到索引,否则都走不到索引 ;
如:
where no < 20  and   name = ‘lucy’ ; 


6、查询结果中含有函数表达式

   有函数表达式也无法走到索引;


六、建索引注意事项 

1、某个列作为条件筛选的结果仍然很大

像”性别”属性,数据库中只会有男、女两种类型,这时候完全没必要使用索引,反而会导致查询结果更糟糕。因为如果不走索引将是个全表的顺序查询(一个随机IO),但是这时候走了索引并且还返回了一个表的很大部分记录,会出现很多的随机IO,无形中增加了操作的IO。

2、组合索引字段顺序

     所以在使用组合索引时候,索引字段的顺序对索引结构影响不大,但是会影响到最终的排序,最终影响以部分字段作为查询条件时候会不会走上索引的问题。

3、哪些场景不适合建索引

     对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于update/insert/delete的每次执行,字段的索引都必须重新计算更新;

4、建索引考虑的条件

     索引尽量少、索引尽量短、合理组织索引字段顺序、索引字段更新频率尽量少、索引应该是常用查询字段且能快速定位少量记录。 


更多学习参考:


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值