2-18-索引

3)详细说明为什么系统的为外键构建索引是普遍的要求(3)

为确保数据的完整性,在对主表操作时,需要对参照表进行加锁操作。如果外键没有索引,查找子记录就会很慢,且参照表被锁的时间很长,进而使很多更改操作阻塞,甚至可能发生死锁。

进行连接查询时,如果不对外键使用索引则会发现查询的速度大大降低。引起全表扫描

4)针对3)有没有例外情况?如果有请简要说明理由(3)

不从父表中删除记录

不更新父表中的主键的值

一般不进行父表和子表的连接查询

盲目为外键加索引还可能造成索引重复


6. 索引与外键

a) 如果没有外键和引用的话,一次修改会导致多次修改

b) 大系统普遍取消外键的关联,取消参照完整性(降低在更新主表时候的过多引用)是提高数据库性能的一个措施。如果有大量的外键关联,则做一次主表查询可能会导致连接多个代码表

c) 如果有外键的话,则需要对外键加上索引,但是不一定,如果该外键不经常使用就不用添加索引,索引建立必须要有理由,无论是外键还是其他字段,并不是外键都要添加索引

d) 如果系统为外键自动添加索引,常常会导致同一字段属于多个索引,为每个外键建立索引,会导致多余索引


2.1 索引概念

1. 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。是一种以原子粒度访问数据的手段,而不是为了大量数据的访问。是一种数据访问方式;索引是顺序存取

2. 索引分类:

聚簇索引:按照数据存放的物理位置为顺序的,索引的叶节点就是物理上的叶节点,聚簇索引能提高多行检索的速度

非聚簇索引: 索引顺序与数据物理排列顺序无关,叶节点仍然是索引节点,保留一个指针指向数据块, 非聚簇索引对于单行的检索很快。

一个表最多只能有一个聚簇索引

3. 索引结构:B 树

4. 索引目的:提高查询效率

5. 索引使用时的考虑

检索比率,一般适用于满足条件的数据量少的情况

磁盘访问,内存访问,记录存储


1. 什么时候使用 B 树索引:

仅当要通过索引访问表中很少一部分行

如果要处理表中多行,而且可以使用索引而不用表

B树索引的结构:由根指向子节点,B树将索引按顺序存储,在叶节点保存索引到字段及其对应数据在表中的位置指针。从根节点开始搜索,通过节点中的指针进入下一级节点,通过比较要查找的索引值和节点中的指针大小选择进入哪个子节点,最终要么找到对应叶节点,要么没找到。叶节点中有指向表中数据的指针。

何时使用:

a、仅需要索引访问表中很少一部分行时,索引提供以原子粒度访问数据的功能,可以快速定位所查找数据的位置;

b、虽然查询行数比较多,当索引包含多个字段,而要访问的字段全部包含在索引中时,查找只需通过索引而不用访问全表时。


7. 系统生成键

1) 系统生成键远好于寻找当前最大值并加 1;好于用一个专用表保存下一个值“且枷锁更新”

2) 系统生成键是串行插入

3) 如果插入并发性过高,在主键索引的创建操作上会发生严重的资源竞争

4) 解决方案:反向键索引(逆向索引);哈希索引

5) 系统生成键使用数字比使用字符串效率高

6) 不使用系统生成键,可能会导致插入时主键取值不唯一,有利于主键的唯一性


2.3 索引的局限性(索引的限制)

1. 为什么不为每一列建立索引

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

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

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

2. 索引会带来的问题

1) 索引有可能降低查询性能,带来磁盘空间的开销和处理开销等

2) 太多的索引,让设计不稳定

3) 对于大量数据检索,索引效率反而更低

4) 创建索引会带来系统的维护和空间的开销

5) 数据修改需求大于检索需求时,索引会降低性能

3. 这些列不应该建立索引

1) 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

2) 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中, 结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

3) 对于那些定义为 text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少,不利于使用索引。

4) 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。


2. 索引的 5 种优点

通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。

在使用分组和排序子句进行数据检索时,同样可以显着减少查询中分组和排序的时间。

通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

3. 应该建立索引的条件

1) 在经常需要搜索的列上,可以加快搜索的速度;

2) 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

3) 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

4) 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;外键建索引由于连接加快还会减少死锁几率。

5) 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

6) 在在经常使用在 WHERE 子句中的列上面创建索引,加快条件的判断速度。


4. 为什么没有使用我的索引?(ppt) (不使用索引的情况)

主要是因为:使用索引反而得不到正确结果;或使查询效率变得更慢

1) 情况 1 :我们在使用 B+树索引,而且谓词中没有使用索引的最前列

表 T,T(X,Y)上有索引,做 SELECT * FROM T WHERE Y=5

跳跃式索引(仅 CBO)

2) 情况 2:使用 SELECT COUNT(*) FROM T,而且 T 上有索引,但是优化器仍然全表扫描,不带任何条件的 count 会引起全表扫描。

3) 情况 3:对于一个有索引的列作出函数查询

Select * from t where f(indexed_col) = value

4) 情况 4 :隐形函数查询(主要是时间和类型变化这种隐形函数查询)

不等于符”<>”会限制索引,引起全表扫描,如果改成 or 就可以使用索引了。

is null 查询条件也会屏蔽索引。

5) 情况 5 :此时如果用了索引,实际反而会更慢

数据量本来不够大,oracle 自己计算后认为不用索引更合算,则 CBO 不会选择用索引

6) 情况 6 :没有正确的统计信息,造成 CBO 无法做出正确的选择;

如果查询优化器认为索引会使查询变慢,则不会使用索引

表分析就是收集表和索引的信息,生成的统计信息会存在 user_tables 这个视图。CBO 根据这些信息决定 SQL 最佳的执行路径。

其他:

1. 对于两个公有字段的表,如果在做外表的表上对该字段建立索引,则该索引不会被使用。因为外表的数据访问方式是全表扫描。

2. 查询使用了两个条件用 or 连接, 如果条件 1 中的字段有索引而条件 2 中字段没有,则仍会全表扫描。

2. 、在以下情况下使用索引会降低查询效率:

   i、在查询中索引列在自定义函数中时,这时候索引将不被使用。

   ii、有隐式类型转化时,索引也不会被使用。

   iii、对于修改较多的表中,使用索引会严重影响数据库更新操作的效率。

   iv、当查询的结果集较大时,索引会影响效率。因为索引是针对点查询的,而不是针对某个范围查询的。一般结果集在10%以下可以考虑使用索引。


2.4 其他索引

2.4.1 位图索引

主要针对大量相同值的列而创建(例如:类别,操作员,部门 ID,库房 ID 等),

索引块的一个索引行中存储键值和起止 Rowid,以及这些键值的位置编码,位置编码中的每一位表示键值对应的数据行的有无.一个块可能指向的是几十甚至成百上千行数据的位置.

这种方式存储数据,相对于 B*Tree 索引,占用的空间非常小,创建和使用非常快.

位图索引:

非常紧凑,块变得复杂,更新操作会导致整个块被锁住,不利于更新,所以创建位图索引的目的是为了查询而不是为了更新

B 树索引不能存控制,位图索引可以存空值


2.4.2 哈希索引

所谓 Hash 索引,实际上就是通过一定的 Hash 算法,将需要索引的键值进行 Hash 运算,然后将得到的 Hash 值存入一个 Hash 表中。每次需要检索的时候,都会将检索条件进行相同算法的 Hash 运算,再和 Hash 表中的 Hash 值进行比较,并得出相应的信息。HASH 索引在有限制条件(需要指定一个确定的值而不是一个值范围)的情况下非常有用。

HASH 的缺点

(1)Hash 索引仅仅能满足"=","IN"和"<=>"查询,不能使用范围查询。由于 Hash 索引比较的是进行 Hash 运算之后的 Hash 值,所以它只能用于等值的过滤,不能用于基于范围的过滤,因为经过相应的 Hash 算法处理之后的 Hash 值的大小关系,并不能保证和 Hash 运算前完全一样。

(2)Hash 索引无法被用来避免数据的排序操作。由于 Hash 索引中存放的是经过 Hash 计算之后的 Hash 值,而且 Hash 值的大小关系并不一定和 Hash 运算前的键值完全一样,所以数据库无法利用索引的数据来避免任何排序运算;

(3)Hash 索引不能利用部分索引键查询。对于组合索引,Hash 索引在计算 Hash 值的时候是组合索引键合并后再一起计算 Hash 值,而不是单独计算 Hash 值,所以通过组合索引的前面一个或几个索引键进行查询的时候,Hash 索引也无法被利用。

(4)Hash 索引在任何时候都不能避免表扫描。前面已经知道,Hash 索引是将索引键通过 Hash 运算之后,将 Hash 运算结果的 Hash 值和所对应的行指针信息存放于一个 Hash 表中,由于不同索引键存在相同 Hash 值,所以即使取满足某个 Hash 键值的数据的记录条数,也无法从 Hash 索引中直接完成查询,还是要通过访问表中的实际数据进行相应的比较,并得到相应的结果。

(5)Hash 索引遇到大量 Hash 值相等的情况后性能并不一定就会比 B-Tree 索引高。对于选择性比较低的索引键,如果创建 Hash 索引,那么将会存在大量记录指针信息存于同一个 Hash 值相关联。这样要定位某一条记录时就会非常麻烦,会浪费多次表数据的访问,而造成整体性能低下。


2.4.3 函数索引

基于函数的索引,类似于普通的索引,只是普通的索引是建立在列上,而它是建立在函数上。当然这会对插入数据有一定影响,因为需要通过函数计算一下,然后生成索引。但是插入数据一般都是少量插入,而查询数据一般数据量比较大。

函数索引还有一个功能,只对部分行建立索引。

原本对 X 构建索引,此时对 F(X)构建索引

在不修改应用程序逻辑的基础上提高查询效率

函数索引与通常 B*树索引的结构,存在很大相似性。区别就在于形成树结构的叶子节点上,保存的不是索引列的取值,而是经过特定的函数处理过的索引列值

但是函数索引的综合消耗大于普通的 B 树索引

适用范围有限,必须函数的使用和定义完全一样

函数索引的针对性很强,如果这个需求不属于关键需求,性价比略差


2.4.4 倒排索引

也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。倒排索引主要由两个部分组成:“单词词典”和“倒排文件”。

“ 倒排索引”是实现单词到文档映射关系的最佳实现方式和最有效的索引结构.

反向索引英文名叫做 Inverted index,顾名思义,是通常意义下索引的倒置。

举个例子: 我们用不同的数字索引不同的句子(比如以下三句在文本中是按照0,1,2的顺序排列的)

0 : "I love you"

1 : "I love you too "

2 : "I dislike you"

如果要用单词作为索引,而句子的位置作为被索引的元素,那么索引就发生了倒置:

"I" : {0,1,2}

"love" : {0, 1}

"you" : {0,1,2}

"dislike" : {2}

如果要检索 "I dislike you" 这句话,那么就可以这么计算 :  {0,1,2} ^ {2} ^ {0,1,2} (这里"^"代表交集)


使用索引降低效率举例:

select count(*) from T,T上有索引,优化器仍然全表扫描

对一个有索引的列作出函数查询select * from where f(col)=value


发布了137 篇原创文章 · 获赞 2 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/m0_37302219/article/details/104872828
今日推荐