ITPub博客

首页 > 数据库 > Oracle > 关于索引的内部信息

关于索引的内部信息

原创 Oracle 作者:jeanron100 时间:2014-12-13 23:39:32 0 删除 编辑
在oracle中对于索引的存储都是采用B树索引来实现。B树索引是比较成熟的一种数据存储结构,在很多的软件中都有大量的应用,oracle中也不例外。
因为B树索引是树形结构。存储的时候也是带枝带叶的。简单来说,索引就像文章里的目录,字典中的词条检索项。
索引分为根节点,分支节点和叶子节点。这种结构对应生活中的树来说明就很形象了。根节点就如同树干,只有一个树干。树干中有很多的树枝,就如分支节点,每个树枝中还会有一些叶子,就如叶子节点。比如我们要存储的数据,把它分为3个分支,那么在根节点中就假设有三个键值 0,500,1000分别代表分支节点中的最小键值。然后在分支节点中就分别对(0,500),(500,100),(1000,1000+)的数据做进一步的细分,比如对于(0,500),我们可以细分为0,200,400,那么就对应(0,200), (200,400),(400,500),这样的话对于(0,500)就存在3个分支节点,然后我们在叶子节点中对分支节点的键值再做一层细分,比如(0,200),我们可以细分为0,50,150.
最后叶子节点的数据就和表的数据行就会有一个最终的映射。数据查找的时候也会高效。
但是话说过来,不管根节点,叶子节点,分支节点,在数据库中都得存储在数据块中。那么一个数据库块中就可能存储多个分支节点或者多个叶子节点。相当于把这些节点的数据都打包了,只是通过逻辑能够很快定位到某个叶子节点在哪个数据块中。
对于索引的一些细节信息,我们可以通过index_stats来查看。这个时候就需要使用analyze这个命令了,在user_indexes中也有一些基本的索引存储信息,这个时候可以使用dbms_stats来分析。

我们来简单的通过实例来说明。
我们创建一个表。
create table index_test as select *from user_objects;
然后创建一个索引。
create index inx_test on index_test(object_id);
使用analyze来分析索引的信息,尽管在新版本中我们建议使用dbms_stats来替代analyze,但是analyze validate structure这个功能时analyze独有的,dbms_stats在这方面还不能完全替代analyze.
analyze index inx_test validate structure;
select height,blocks,br_blks,lf_blks,lf_rows,del_lf_rows from index_stats; --高度  索引总块数   枝干块数    叶子块数  叶子内行数    叶子中被删除的行数  
    HEIGHT     BLOCKS    BR_BLKS    LF_BLKS    LF_ROWS DEL_LF_ROWS
---------- ---------- ---------- ---------- ---------- -----------
         1          8          0          1         73           0   
可以看到,索引的高度是1,目前分支节点占有一个数据块,叶子节点占用一个数据块,叶子节点对应的数据行数有73行。
这个时候有一个奇怪的现象是表Index_test中有74条数据,但是为什么73行呢。

SQL> select count(*)from index_test;

  COUNT(*)
----------
        74

SQL> select count(*)from index_test where object_id is null; 

  COUNT(*)
----------
         1
因为我们存在一条记录中object_id位空值了,所以没有作为索引列。
我们来随机抽取几条数据作为后续的dml操作基础。
 select *from (select object_id from index_test order by dbms_random.value()) where rownum<5;
 OBJECT_ID
----------
     15287
     22180
     22295
     14019

我们就选择第一条记录。做一个update操作。
update index_test set object_id=11111 where object_id=15287;
commit;
analyze index inx_test validate structure;--再次分析索引
select height,blocks,br_blks,lf_blks,lf_rows,del_lf_rows from index_stats;
    HEIGHT     BLOCKS    BR_BLKS    LF_BLKS    LF_ROWS DEL_LF_ROWS
---------- ---------- ---------- ---------- ---------- -----------
         1          8          0          1         74           1
可以很清晰的看到叶子内行数从73变为74,然后 叶子中被删除的行数 也从0变为1.
这是因为update也是一个delete+insert的操作,新增加的一行是object_id=15287被删除时留下的。
我们来尝试一个Insert操作。
insert into index_test select *from index_test;
commit;
analyze index inx_test validate structure; --再次分析索引
select height,blocks,br_blks,lf_blks,lf_rows,del_lf_rows from index_stats;
    HEIGHT     BLOCKS    BR_BLKS    LF_BLKS    LF_ROWS DEL_LF_ROWS
---------- ---------- ---------- ---------- ---------- -----------
         1          8          0          1        146           0
这个时候叶子内行数从74变为146. 可以这么理解73*2=146. 因为表中的非null数据有73行,所以再次插入的时候对应的叶子内行数就是73*2=146.

我们插入较多的数据来看看叶子节点的存储情况。
insert into index_test select *from index_test;
/
commit;  --插入了两次
analyze index inx_test validate structure;  --再次分析索引
select height,blocks,br_blks,lf_blks,lf_rows,del_lf_rows from index_stats;
     HEIGHT     BLOCKS    BR_BLKS    LF_BLKS    LF_ROWS DEL_LF_ROWS
---------- ---------- ---------- ---------- ---------- -----------
         2          8          1          2        584           0
可以看到叶子内行数变化很大,同时叶子节点块变为了2个。
如果再逐渐插入数据,可以看到分支节点,叶子节点的变化情况。

我们这个时候可以换个思路,来使用dbms_stats来查看一下信息。
user_indexes中的信息还有比较粗略的。我们来验证一下是否和analyze分析的Index_stats结果一致。

SQL> select blevel,leaf_blocks from user_indexes where index_name='INX_TEST';

    BLEVEL LEAF_BLOCKS
---------- -----------
         0           1
这个时候看起来信息过旧了,我们使用dbms_stats来收集一下统计信息。
exec dbms_stats.gather_index_stats(ownname=>'N1',indname=>'INX_TEST');
再次查看结果就跟预期的一致了。

select blevel,leaf_blocks from user_indexes where index_name='INX_TEST';

    BLEVEL LEAF_BLOCKS
---------- -----------
         1           2

索引的内部信息还是比较抽象的,要做细致的分析还是要下不少的功夫。不过对于索引的很多细节信息,可以说都属于技术级别,都在oracle内部做了封装。我们可以根据兴趣来了解一下。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/23718752/viewspace-1367045/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
感谢厚爱,阵地已转移到微信公众号端。 公众号:jianrong-notes

注册时间:2012-05-14

  • 博文量
    1890
  • 访问量
    8434892