分享

Java面试之数据库——数据库索引

 Levy_X 2018-10-06

原文:https://blog.csdn.net/sundacheng1989/article/details/53117172

https://www.cnblogs.com/gavinsp/p/5513536.html

https://www.cnblogs.com/lpshou/p/3364282.html

最近使用到Oracle数据库的索引比较多,所以就想好好研究一下索引到底是什么。毕竟作为一个Application Developer,而不是DBA,所以这篇文字也是很通俗,特别浅显的描述了一下索引相关的概念。

 

为什么需要索引?数据在磁盘上是以块的形式存储的。为确保对磁盘操作的原子性,访问数据的时候会一并访问所有数据块。磁盘上的这些数据块与链表类似,即它们都包含一个数据段和一个指针,指针指向下一个节点(数据块)的内存地址,而且它们都不需要连续存储(即逻辑上相邻的数据块在物理上可以相隔很远)。

 

举个例子来讲,我们有一个数据表User.为了简便,这个表没有主键。

 

Identity

Name

Age

Grade

1

Robin

28

90

5

Lilei

26

60

3

Hanmei

25

50

4

Lucy

27

66

2

Lily

29

80

 

虽然这些数据都存在于一个User表中,但是物理上,这些数据可能存储在分散的数据块中。

 

查找Lily这个人的信息已知LilyIdentity2 select * fromUser where Identity= 2.

 

在查找的时候,首先找到这个表的第一条记录所在的数据库地址,然后发现Identity1,并不是所需要的值,然后在这个数据库的底端,找到了下一个数据块的地址。(这个类似于链表),如此一来,查询了5次才找到了所需要的值。(为了简单起见,我们考虑Identity不能有重复值)

 

为了加快搜索速度,这里就出现了索引。索引是对某个字段进行排序的一种方式。对表中的某个字段建立索引会创建另一种数据结构,其中保存着字段的值,每个值又指向与它相关的记录。这种索引的数据结构是经过排序的,因而可以对其执行二分查找。

 

对上个表的Identity字段进行索引,就是在数据库存储空间上创建一块专用的控件,把User表的所有的Identity字段的值拿出来放到这里,并且对这些值进行排序,并且每个值都携带着这个Identity对应的行所在数据块的地址。因为Identity是进过排序的,按照一定的数据结构存储的,所以数据库引擎在查找的时候,比如说查找identity5,引擎就会计算,5大概在整个排序结构的大致地方,然后到那里去拿出这个值看看是不是,不是的话就再次相应的向左或者向右移动去寻找。(这里用到的知识都是大学时候的数据结构的知识,二分法查找,相对于毫无头绪的一个一个的查找,二分法的查找速度明显的提高,达到了log2 N,其实这有多快我也不明白,反正就记得当时学的时候,确实是比一般查找快多了。)

 

通俗的来讲,就是根据你指定的列,建立一个遵循一定数据结构的区域,这些区域可以快速定位到相应数据库字段所在的磁盘地址。

 

 

索引的好处是特别明显的,那就是大大的提高了查询的速度。但是相对应的也带来了一些不好的地方。


第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。

第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

 

 

最后还有一点需要注意的是,我们在数据库上对于某个字段建立了索引,那么什么情况下才走索引呢?

 

比如 select * from User where Identity= 2 这条语句,是走索引查询的。因为是否走索引取决于这条查询语句的where子句。数据库引擎发现你的where语句中有identity,那么就会从identity的索引数据结构中进行检索。曾经看到有人说select *会降低检索速度,这个跟索引没关系,select * 降低检索速度,是因为从数据库服务器端到客户端的网络传输是有时间的,select * 中难免包含着不必要的字段,所以传输起来会比较慢。

 

接下来单纯的比较一下select * select 单个字段在速度上的区别。如果数据量非常非常大的话,这种速度上的差别是非常明显的。下边这个例子,是从相同的数据库表中去拿数据。

 

当只是返回一个OUT_ID字段的时候,你可以看到49秒钟的时候就处理了30万条数据。





这时候我们使用select * 这种方式,我们发现,在用事一分钟的时候,才处理了3万条数据。




从上边的对比中我们可以看出,在数据量非常大而且数据表字段非常多的时候,这两种方式在检索时间上的差别还是非常大的。


---------------------------------------------------------------------------------------------------------------------------------------

1、索引定义
  数据库索引好比是一本书前面的目录,能加快数据库的查询速度。索引是对数据库表中一个或多个列(例如,employee 表的姓氏 (lname) 列)的值进行排序的结构。如果想按特定职员的姓来查找他或她,则与在表中搜索所有的行相比,索引有助于更快地获取信息。

2、建立索引的优缺点:
优点:
1.大大加快数据的检索速度;
2.创建唯一性索引,保证数据库表中每一行数据的唯一性;
3.加速表和表之间的连接;
4.在使用分组和排序子句进行数据检索时,可以显著减少查询中分组和排序的时间。
缺点:

  1.索引需要占用数据表以外的物理存储空间

  2.创建索引和维护索引要花费一定的时间

  3.当对表进行更新操作时,索引需要被重建,这样降低了数据的维护速度。
3、索引类型:
根据数据库的功能,可以在数据库设计器中创建索引:唯一索引、主键索引和聚集索引。 尽管唯一索引有助于定位信息,但为获得最佳性能结果,建议改用主键或唯一约束。

唯一索引: UNIQUE 例如:create unique index stusno on student(sno);
表明此索引的每一个索引值只对应唯一的数据记录,
对于单列惟一性索引,这保证单列不包含重复的值。对于多列惟一性索引,保证多个值的组合不重复。
主键索引: primary key
数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。 在数据库关系图中为表定义
主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。

聚集索引(也叫聚簇索引):cluster
在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。 如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。
 
4、索引的实现方式
1 B 树 我们经常听到B 树就是这个概念,用这个树的目的和红黑树差不多,也是为了尽量保持树的平衡,当然红黑树是二叉树,但B 树就不是二叉树了,节点下面可以有多个子节点,数据库开发商会设置子节点数的一个最大值,这个值不会太小,所以B 树一般来说比较矮胖,而红黑树就比较瘦高了。
关于B 树的插入,删除,会涉及到一些算法以保持树的平衡,这里就不详述了。ORACLE的默认索引就是这种结构的。
如果经常需要同时对两个字段进行AND查询,那么使用两个单独索引不如建立一个复合索引,因为两个单独索引通常数据库只能使用其中一个,而使用复合索引因为索引本身就对应到两个字段上的,效率会有很大提高。

2 散列索引

第二种索引叫做散列索引,就是通过散列函数来定位的一种索引,不过很少有单独使用散列索引的,反而是散列文件组织用的比较多。
散列文件组织就是根据一个键通过散列计算把对应的记录都放到同一个槽中,这样的话相同的键值对应的记录就一定是放在同一个文件里了,也就减少了文件读取的次数,提高了效率。
散列索引呢就是根据对应键的散列码来找到最终的索引项的技术,其实和B树就差不多了,也就是一种索引之上的二级辅助索引,我理解散列索引都是二级或更高级的稀疏索引,否则桶就太多了,效率也不会很高。

3 位图索引

位图索引是一种针对多个字段的简单查询设计一种特殊的索引,适用范围比较小,只适用于字段值固定并且值的种类很少的情况,比如性别,只能有男和女,或者级别,状态等等,并且只有在同时对多个这样的字段查询时才能体现出位图的优势。
位图的基本思想就是对每一个条件都用0或者1来表示,如有5条记录,性别分别是男,女,男,男,女,那么如果使用位图索引就会建立两个位图,对应男的10110和对应女的01001,这样做有什么好处呢,就是如果同时对多个这种类型的字段进行and或or查询时,可以使用按位与和按位或来直接得到结果了。

B 树最常用,性能也不差,用于范围查询和单值查询都可以。特别是范围查询,非得用B 树这种顺序的才可以了。
HASH的如果只是对单值查询的话速度会比B 树快一点,但是ORACLE好像不支持HASH索引,只支持HASH表空间。
位图的使用情况很局限,只有很少的情况才能用,一定要确定真正适合使用这种索引才用(值的类型很少并且需要复合查询),否则建立一大堆位图就一点意义都没有了。

5 Hash索引缺点

 MySQL的B-Tree索引和Hash索引的区别



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多