索引的使用场景:
1.对应的索引字段经常被查询,且返回的数据结果占总数据量的一小部分

2.有外键约束的单个或多个字段上,需要建立索引。避免在更新主表的主键值,插入数据或删除数据时,对整张表的表锁出现。

3.唯一键约束,有相对应的索引存在


索引的属性:

    索引与表中数据独立,增加或删除索引对表数据库无影响,只不过对应数据查询速度变慢,索引会降低dml操作性能(需要额外更新索引数据)

    1.可用性

    默认属性为可用,一个unuseable索引,dml操作不在维护对应索引且被优化器忽略,相对于删除一个索引继而创建它,可使用使索引不可用然后rebuild。无效索引或分区索引不占用空间,当把索引置成无效时,对应的存储空间被删掉,(对应分配的区段给删除掉).

    2.可见性

    默认可见。一个invisible索引,dml操作进行维护,默认优化器不使用此索引。把一个索引置成不可见,是删除它或者更改为无效状态两者中的一种。把索引置成不可见非常有用,在删除以前移除索引或临时使用索引对应所有应用都没有影响。


    相同字段不同顺序可以创建不同索引。

    例如:create index ind_1 on halee(empno,ename);

          create index ind_2 on halee(ename,empno);

index scan:I/O次数跟使用的索引的高度一致,在一次查询数据中。

full index scan:当谓语(where clause)中包含索引字段的过滤条件,都会走索引全扫描,前提是必须前置字段在前,如果排序字段与创建索引顺序不同,则不会使用索引全扫描

    例如:全索引扫描场景

    索引创建顺序为 empno,ename,sal;

1.查询字段全部在索引里,直接从索引中获取不在访问对应表

explain plan for

select empno,ename,sal from marlie where sal >= 3000 order by empno,ename;

-----

Plan hash value: 3148600482

 

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

| Id  | Operation        | Name              | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT |                   |     3 |    99 |     1   (0)| 00:00:01 |

|*  1 |  INDEX FULL SCAN | IND_MARLIE_COMPLI |     3 |    99 |     1   (0)| 00:00:01 |

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

2.查询除了索引字段以前的其他字段,需要通过索引rowid来访问表来回去对应数据值

    explain plan for

    select empno,ename,sal,HIREDATE from marlie where sal >= 3000 order by empno,ename;

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

    Plan hash value: 3449361140

     

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

    | Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |

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

    |   0 | SELECT STATEMENT            |                   |     3 |   126 |     2   (0)| 00:00:01 |

    |   1 |  TABLE ACCESS BY INDEX ROWID| MARLIE            |     3 |   126 |     2   (0)| 00:00:01 |

    |*  2 |   INDEX FULL SCAN           | IND_MARLIE_COMPLI |     1 |       |     1   (0)| 00:00:01 |

3.查询字段只包括索引字段,排序非创建顺序,需要有额外排序操作

    explain plan for

    select empno,ename,sal from marlie where sal >= 3000 order by ename,empno;

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

    Plan hash value: 584562644

     

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

    | Id  | Operation        | Name              | Rows  | Bytes | Cost (%CPU)| Time     |

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

    |   0 | SELECT STATEMENT |                   |     3 |    99 |     2  (50)| 00:00:01 |

    |   1 |  SORT ORDER BY   |                 |     3 |    99 |     2  (50)| 00:00:01 |

    |*  2 |   INDEX FULL SCAN| IND_MARLIE_COMPLI |     3 |    99 |     1   (0)| 00:00:01 |

4.查询字段除索引字段外还有其他字段,排序非创建顺序,直接不会走索引全所描

    explain plan for

    select empno,ename,sal,HIREDATE from marlie where sal >= 3000 order by ename,empno;

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

    Plan hash value: 1152818333

     

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

    | Id  | Operation          | Name   | Rows  | Bytes | Cost (%CPU)| Time     |

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

    |   0 | SELECT STATEMENT   |        |     3 |   126 |     4  (25)| 00:00:01 |

    |   1 |  SORT ORDER BY     |        |     3 |   126 |     4  (25)| 00:00:01 |

    |*  2 |   TABLE ACCESS FULL| MARLIE |     3 |   126 |     3   (0)| 00:00:01 |

fast full index scan:属于full index scan一种,当查询的字段全部在索引里,且没有特殊的排序要求。

以下两种情况会替代全表扫描:

    1.索引包含所有的查询字段

    2.一行数据全部为null的值不会显示在结果集中

        2.1.索引字段有一个字段有not null约束

        2.2.where条件里有过滤null值的条件,保证全部为null的不展示出来


index range scan:

where条件中索引字段对应有过滤条件,且索引不是唯一索引,一个key对应多个rowid,就会使用索引范围扫描,在条件中有范围查询 between and,会走index range scan。

    explain plan for

     select empno,ename,sal,deptno from marlie where empno=7521;-- 索引字段出现在where中

    ----

    Plan hash value: 3540606923

     

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

    | Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |

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

    |   0 | SELECT STATEMENT            |                   |     1 |    46 |     2   (0)| 00:00:01 |

    |   1 |  TABLE ACCESS BY INDEX ROWID| MARLIE            |     1 |    46 |     2   (0)| 00:00:01 |

    |*  2 |   INDEX RANGE SCAN          | IND_MARLIE_COMPLI |     1 |       |     1   (0)| 00:00:01 |


index unique scan:

一个key对应0或1条数据,where条件为等值查询,索引字段为唯一键值,当查询到一个符合条件的记录即可会停止对应查询进程。与index range scan对应。

在empno字段创建了唯一索引

    explain plan for

     select empno,ename,sal,deptno from marlie where empno=7521;

    ------

    Plan hash value: 260264523

     

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

    | Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |

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

    |   0 | SELECT STATEMENT            |                   |     1 |    17 |     1   (0)| 00:00:01 |

    |   1 |  TABLE ACCESS BY INDEX ROWID| MARLIE            |     1 |    17 |     1   (0)| 00:00:01 |

    |*  2 |   INDEX UNIQUE SCAN         | UIND_MARLIE_EMPNO |     1 |       |     0   (0)| 00:00:01 |


index skip scan:

使用符合索引的逻辑子索引进行扫描获取数据。在复合索引前导列数据只有很少的几个值,非前导列有很多非重复的值,在where条件中使用非前导列查询时,会走index skip scan.

逻辑上按照前导列的非重复值的个数,把复合索引分成若干个子索引。

举例如下:

在表halee中创建 sex,id复合索引,分析表后:

explain plan for

 select * from halee where id = 2050;

----

Plan hash value: 1329500493

 

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

| Id  | Operation        | Name          | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT |               |     2 |    14 |     4   (0)| 00:00:01 |

|*  1 |  INDEX SKIP SCAN | IND_HALEE_COM |     2 |    14 |     4   (0)| 00:00:01 |


实际执行类似:

 select * from halee where sex = 1 and id = 2050

union all

 select * from halee where sex = 0 and id = 2050;


index clustering factor:

    用于衡量索引数据排序是否工整,顺序排列对应的相邻叶子块 对应的行存储在同一个数据块中(读取数据都是按照块读取的),这样可降低IO次数,索引聚集因子就很小,接近于表数据对应的块个数。

    只有尽可能的降低表的集群因子。一个索引怎么查询都不走索引或强制执行花费更大,有可能是集群因子过大导致。


reserve key indexes:把字段值对应的十六进制 按照倒叙的顺序存储

优点:避免热块操作,特别是在rac中,不同的实例操作相同的数据块。增加了插入性能。

缺点:在范围查询中,不能使用反转索引进行查询。


ascending and descending indexes:

ascending :以升序的方式存储数据,默认情况下,字符串类型按照值对应的字节数存储,数字类型按照从小大小数据,时间类型按照从古至今的方式存储。

descending:以倒叙的方式存储数据。

优点:在索引字段对应排序时,不需要额外的排序操作。


key compression:可以压缩主键对应的b-tree索引,或者是索引组织表;键值压缩,可以大大缩小索引存储所需空间。

每个索引都有公共部分(group piece)及唯一部分(unique piece),压缩后更改为 前缀部分(prefix)和后缀部分(suffix),prefix对应group piece,suffix对应unqiue piece,prefix对应索引对应的字段值,suffix对应rowid

压缩前,存储类似:压缩后

20 1234 AAASMSAAEAAAACzAAA

20 1234 AAASMSAAEAAAACzAAB

30 2154 AAASMSAAEAAAACzAAC

40 1111 AAASMSAAEAAAACzAAD

40 1112 AAASMSAAEAAAACzAAE

20 1234

AAASMSAAEAAAACzAAA

AAASMSAAEAAAACzAAB

30 2145

AAASMSAAEAAAACzAAC

40 1111

AAASMSAAEAAAACzAAD

40 1112

AAASMSAAEAAAACzAAE




位图索引(bitmap index)

适用环境:

  1. 字段中数据基数少,即唯一值不多。

  2. 表中更新少或几乎没有.

表中更新数据时,直接把索引键对应的值所有的行都进行锁定,不是锁定某一更改的行。

针对与某个bitmap索引,每一行都有一个对应的值来标识该行数据是否满足索引要求

存储如下:

col_valuerow1row2row3row4row5row6row7
M1000111
F0111000

针对bitmap类型的值来进行计算数量等类似的查询,可以创建爱你bitmap join index

例如在dept.dname字段上创建bitmap索引,基表为emp

create bitmap index bind_emp_dep_dname on emp(dept.dname)

from emp,dept where emp.deptno=dept.deptno;

类似如下的查询,会直接返回结果:

select count(*) from emp,dept where emp.deptno=dept.deptno and dname='ACCOUNTING';


bitmap index存储:

使用b-tree的方式存储每个索引键值,每个位图都存储在叶子节点上。

每个位图索引以b-tree方式存储有下面三部分组成:

  1. 每个索引值以索引键值开头

  2. 每个范围以rowid最小值和最大值标志

  3. 每个范围内的rowid的位图值