数据库索引学习

一、索引介绍

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

索引其实就是在数据库存储数据之外,还维护着另外的满足某种查询算法的数据结构,这些数据结构再以某种方式指向真实的存储数据,然后在现有的数据结构上实现快速查询。(找了张很不错的二叉树的图来理解索引,现在大多的索引都是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、建索引考虑的条件

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

更多学习参考:

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

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-06 15:26:13

数据库索引学习的相关文章

MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引

这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一些准备工作要做,之后的探索都是基于这些准备工作. 首先需要建立一个数据库和一些集合,这里我就选用一个国内手机号归属地的库,大约32W条记录,数据量不大,不过做一些基本的分析是够了. 首先我们建立一个数据库,叫做db_phone,然后导入测试数据.测试数据就是一些手机号归属地的信息.单个文档长这个样子

数据库索引B+树

面试时无意间被问到了这个问题:数据库索引的存储结构一般是B+树,为什么不适用红黑树等普通的二叉树? 经过和同学的讨论,得到如下几个情况: 1. 数据库文件是放在硬盘上,每次读取数据库都需要在磁盘上搜索,因此需要考虑磁盘寻道时间,我们都知道磁盘寻道开销是非常大的.同时,索引一般也是非常大的,内存不能放下,因此也会放在磁盘上.(另外,还与局部性原理与磁盘预读有关系). 2. B+树所有的关键字都出现在叶子节点的链表(稠密索引)中,且链表中的关键字是有序的.非叶子节点只起索引作用(稀疏索引). 叶子节

数据库索引的实现原理

1 什么是索引 数据库索引,是数据库管理系统中一个排序的数据结构. 对数据记录建立索引后,每条索引记录包含:(1)值与相应 数据记录 被索引列的值一样的键(2)相应数据记录的地址. “索引的实现通常使用B树及其变种B+树”,即采用B树等对 索引记录 按键进行排序. 根据数据库的功能,可以在数据库设计器中创建三种索引:唯一索引(唯一).主键索引(唯一非空)和聚集索引(行间逻辑顺序与物理顺序一致,提供更快数据访问). 2 使用索引的利弊 利:加快查询速度 弊:索引需要占用空间:创建和维护索引(插入.

SQL索引学习-索引结构

前一阵无意中和同事讨论过一个SQL相关的题(通过一个小问题来学习SQL关联查询),很惭愧一个非常简单的问题由于种种原因居然没有回答正确,数据库知识方面我算不上技术好,谈起SQL知识的学习我得益于2008年进的一家公司,有几个DBA技术相当专业,正好手上有一个项目遇到了一些数据库查询性能问题,就试着想办法优化,于是自己将相法和DBA沟通后,居然得到了他们的赞同,让我信心大增,后来一段时间我又主动找他们聊了一些其它的知识,所以在数据库索引这块我算是相对一般的.net程序员要更加有见解一些.当时我们部

MariaDb数据库管理系统学习(二)使用HeidiSQL数据库图形化界面管理工具

HeidiSQL 是一款用于简单化的 MySQL 服务器和数据库管理的图形化界面.该软件允许你浏览你的数据库,管理表,浏览和编辑记录,管理用户权限等等.此外,你可以从文本文件导入数据,运行 SQL查询,在两个数据库之间同步表以及导出选择的表到其它数据库或者 SQL 脚本当中.HeidiSQL 提供了一个用于在数据库浏览之间切换 SQL 查询和标签带有语法突出显示的简单易用的界面.其它功能包括BLOB 和 MEMO 编辑,大型 SQL 脚本支持,用户进程管理等.该软件资源开放. MariaDB安装

数据库索引及其数据结构

出处:http://blog.linezing.com/?p=798 转载: http://blog.csdn.net/kennyrose/article/details/7532032 说白了,索引问题就是一个查找问题...   数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询.更新数据库表中数据.索引的实现通常使用B树及其变种B+树. 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法.

SQL Server调优系列进阶篇(如何维护数据库索引)

原文:SQL Server调优系列进阶篇(如何维护数据库索引) 前言 上一篇我们研究了如何利用索引在数据库里面调优,简要的介绍了索引的原理,更重要的分析了如何选择索引以及索引的利弊项,有兴趣的可以点击查看. 本篇延续上一篇的内容,继续分析索引这块,侧重索引项的日常维护以及一些注意事项等. 闲言少叙,进入本篇的主题. 技术准备 数据库版本为SQL Server2012,前几篇文章用的是SQL Server2008RT,内容区别不大,利用微软的以前的案例库(Northwind)进行分析,部分内容也会

【SQLSERVER】数据库索引维护/优化

好几个月没更新博客了,一方面是因为换工作和搬家的原因,比较忙:另一方面是因为觉得对数据库的理解还不够深刻,花了些时间在学习上. 最近到新公司后,做了些数据库索引优化和维护上的工作,趁着今天有空,写个博客与大家分享下,其实一些源码也是网上拷贝的,只不过是做了些改进,主要想分享的是一个优化的思路. 一.索引的利弊   优点: 1.大大加快数据的检索速度: 2.创建唯一性索引,保证数据库表中每一行数据的唯一性: 3.加速表和表之间的连接: 4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组

转 漫谈数据库索引

漫谈数据库索引 一.引言 二.B-Tree B-TreeB+TreeMsSqlB+TreeOracleSysbaseB-TreeB-Tree 不同于(二叉树,最多有两个子树),一棵阶的满足以下条件: )每个结点至多有个孩子: )除根结点和叶结点外,其它每个结点至少有个孩子: )根结点至少有两个孩子(除非该树仅包含一个结点): )所有叶结点在同一层,叶结点不包含任何关键字信息: )有个关键字的非叶结点恰好包含个孩子: B-TreeM=4 Key[]Son[]B-TreeKey[]KKKey[]KK