时间:2021-07-01 10:21:17 帮助过:5人阅读
数据库索引调优是一项技术活,不能仅仅靠理论,因为实际情况千变万化,而且各种数据库本身存在很复杂的机制,如查询优化策略和各种引擎的实现等。但同时这些理论是索引调优的基础,只有在明白理论的基础上,才能对调优策略进行合理推断并了解其背后的机制,然后结合实践中不断的实验和摸索。
索引其实就是在数据库存储数据之外,还维护着另外的满足某种查询算法的数据结构,这些数据结构再以某种方式指向真实的存储数据,然后在现有的数据结构上实现快速查询。(找了张很不错的二叉树的图来理解索引,现在大多的索引都是B+树的结构,基本上没有使用二叉树的)。
索引本身也很大,不可能全部存储在内存中,往往以索引文件的形式存储在磁盘上。所以索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高出好多好多,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的复杂度。换句话说,索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数。而B+树结构在实际的应用中刚好满足减少物理I/O操作的要求,来胜任索引结构再合适不过了(下面介绍)。
数据库查询大部分时间都消耗在了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请求的次数。
在学校时候理解数据库中的查询就认为是一般的顺序查找,现在再回想这种复杂度为O(n)的算法在数据量很大的情况下简直不敢想想,那么多牛逼的查询算法像二分查找、二叉树查找等 在实际的应用上还真没有好好琢磨过。找了些对比B-Tree、B+Tree结构的资料(下图很好诠释了两种结构的区别)。
1、B-Tree、B+Tree主要区别:
B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历。
2、B+ 树的优点在于:
常索引有 唯一索引、主键索引、聚集索引,有时候为了了更多的提高mysql效率可建立组合索引,遵循“最左前缀“原则。最左前缀:顾名思义,就是最左优先。例如,对于表title(id,no,name,age)我们创建了以三个字段的组合多列索引(no,name,age),相当于创建了(no)单列索引,(name,fname)组合索引以及(no,name,age)组合索引。
其他的不多说了,这次主要是对组合索引的学习,下面列出组合索引“最左前缀”的场景 (就以上表title为例、通过查看执行计划是否走了索引):
如 where no = n and age = 20 少了索引中间列 name ,这时候只用到了索引的第一列no ,后面age虽然也在索引中,由于缺少name列 无法和左前缀连接;
如果少了索引的第一列no 如:where name = ‘jeck’ and age = 20 这样不匹配最左前缀,就无法走索引了。
如果在某列中使用了 % 模糊匹配,要看%的位置判断是否能走到索引, %在字符串的最后则可以使用索引 ,如:
where no = 1 and name like ‘luc%’
; 但是,如果%在前面就不行 如:where no = 1 and name like ‘%cy’ ;
如果在sql中用到了 < 、 >的范围查找 ,且只有一个范围列的 就可以走到索引,否则都走不到索引 ;
如:where no < 20 and name = ‘lucy’ ;
有函数表达式也无法走到索引;
像”性别”属性,数据库中只会有男、女两种类型,这时候完全没必要使用索引,反而会导致查询结果更糟糕。因为如果不走索引将是个全表的顺序查询(一个随机IO),但是这时候走了索引并且还返回了一个表的很大部分记录,会出现很多的随机IO,无形中增加了操作的IO。
所以在使用组合索引时候,索引字段的顺序对索引结构影响不大,但是会影响到最终的排序,最终影响以部分字段作为查询条件时候会不会走上索引的问题。
对于记录比较少的表,增加索引不会带来速度的优化反而浪费了存储空间,因为索引是需要存储空间的,而且有个致命缺点是对于update/insert/delete的每次执行,字段的索引都必须重新计算更新;
索引尽量少、索引尽量短、合理组织索引字段顺序、索引字段更新频率尽量少、索引应该是常用查询字段且能快速定位少量记录。
http://www.ituring.com.cn/article/986 http://www.cnblogs.com/yangecnu/archive/2014/03/29/Introduce-B-Tree-and-B-Plus-Tree.html http://blog.codinglabs.org/articles/theory-of-mysql-index.html http://www.blogjava.net/happyenjoylife/archive/2011/12/17/366639.html
版权声明:本文为博主原创文章,未经博主允许不得转载。
数据库索引学习
标签:索引 数据库