Oracle优化之B树索引

B树索引

目前数据库中最常用的索引,构造类似于二叉树,能根据键值提供一行或一个行集的快速访问,其中的’B’代表平衡, 通常使用在频繁使用查询谓词的列上,一般这类列的选择度都较高。

使用场景

  1. 当我们希望从表中只返回少量的数据(占比很小,这个比例通常经验值是5%,不过根据表的不同也有不用,一个瘦表(通常只有几列)可能在20%-30%,一个胖表(列很多或列很宽)可能在2%-3%)时会使用索引。如下例:

T1表插入从1到10w的数字只有一列,t3_2利用下例中的t3建表,建表sql

create table t3_2 as select id,name,name||name||name||name c3,name||name||name||name||name c4 from t3

分别在id列建立索引,收集统计信息

以上两个查询中的数值分别是全表扫描与索引范围查询的临界值

  1. 当我们想要查询大量数据,但是只要返回索引的列或者只通过索引列就能得到结果的话,索引也会起到作用

3、数据在磁盘上的物理组织也会对索引的使用有影响,如以下的例子,我们创建两个实验表t2/t3,向t2中顺序的插入10w条数据,同时生成一组随机数据。将t2按照随机数排序插入到t3中,目的是打乱数据的物理存储位置。

 

begin

  for  i in 1..100000 loop

    insert into t2 values(i,rpad(dbms_random.random,75,'*'));

    end loop;

    commit;

end;

create table t3 as select * from t2 order by name

create index idx_1 on t2(id)

create index idx_2 on t3(id)

begin

  dbms_stats.gather_table_stats

  ('scott','t2');

begin

  dbms_stats.gather_table_stats

  ('scott','t3');

  end;

  end;

在对表进行收集统计信息后,分别对t2/t3查询相同范围的数据

select * from t2 where id between 87 and 1000

select * from t3 where id between 87 and 1000

以上三个查询的结果是相同的,但是相同的查询数据库的开销与io上升的差异十分明显。

原因是当向一个表中填充数据时如果按照行主键或者建立索引的列顺序填充,序号相邻的行存储位置一般也会相邻,当你发出一个范围查询的时候你想要的行通常也在同样的块上,即使你要查找大量的行,通过索引范围扫描的读取的块里也许就包含了你想要的行。如下图,相同数量的行数在未打乱顺序的t2中分布在11个数据块,在顺序被打乱的t3中分布在631个块。

如果行被分散的存储在不同位置上,此时强制使用索引范围扫描就会是个灾难,使用全表扫描反而更好。

总结

  1. 通过索引访问表中的数据占比越少越有效
  2. 如果能使用索引列回答问题(只用到索引列不用访问表)那么返回数据占比很大索引也是有效的
  3. 数据的物理组织有时未按照索引列或主键列有序的填充表,会影响索引的使用
  4. B树索引经过大量的插入删除操作以后一个是容易使树不平衡,再一个是删除后空间不回收。所以定期重建索引非常有必要。
  5. 空值会影响索引的使用,在有空值的列上通过与虚拟列建立组合索引,可以使优化器选择索引。而且索引的大小并没有明显变化

create table t5 as select u.OBJECT_NAME,u.DATA_OBJECT_ID from user_objects u

create index t5_1 on t5(DATA_OBJECT_ID)

create table t6 as select * from t5

create index t6_1 on t6(DATA_OBJECT_ID,0)

 

begin

  dbms_stats.gather_table_stats

  ('scott','t5');

dbms_stats.gather_table_stats

  ('scott','t6');

  end;

 

 

猜你喜欢

转载自blog.csdn.net/weixin_44033089/article/details/86514103