在执行数据库查询时,索引是一个提高查询效率的好方法,但是如果对索引的管理不当,可能起到相反的效果,下面介绍索引的查询和管理:
查询:
索引扫描可以分两步:
1)扫描索引得到rowId
2)通过rowid读取具体数据(前提索引中没有你查询的数据,需要通过rowid去数据块查询,否则直接忽略第二部)
每步都是单独的一次I/O,但是对于索引,由于经常使用,绝大多数都已经CACHE到内存中,所以第1步的 I/O经常是逻辑I/O,即数据可以从内存中得到。但是对于第2步来说,如果表比较大,则其数据不可能全在内存中,所以其I/O很有可能是物理I/O,这 是一个机械操作,相对逻辑I/O来说,是极其费时间的。所以如果多大表进行索引扫描,取出的数据如果大于总量的5% —— 10%,使用索引扫描会效率下降很多。所以要求索引要求唯一性比较高(位图索引除外)。
管理:
<!--
数据删除,对应的索引快中某删除了索引条目,只有当有键值进入该索引块时才能将空间收回。而持续增加的索引键值永远只会向插入排在前面的索引块中,因此这种索引里的空间几乎不能收回,而只有其所含的索引条目全部删除时,该索引块才能被重新利用。
-->
在使用索引提高查询效率的同时,可能需要对数据进行数据删除(DML),对应的索引也会改变。就可能出现下面索引碎片情况。
解决办法:
重建索引:
当我们重建索引以后,在物理上所能获得的好处就是能够减少索引所占的空间大小(特别是能够减少叶子
节点的数量)。而索引大小减小以后,又能带来以下若干好处:
1) CBO对于索引的使用可能会产生一个较小的成本值,从而在执行计划中选择使用索引。
2) 使用索引扫描的查询扫描的物理索引块会减少,从而提高效率。
3) 由于需要缓存的索引块减少了,从而让出了内存以供其他组件使用。
SQL> select count(*) from index_stats;
COUNT(*)
----------
执行分析索引命令:
SQL> analyze index my_bit_idx validate structure;
Index analyzed.
再次查看 index_stats 已经有了一条数据
SQL> select count(*) from index_stats;
COUNT(*)
----------
把数据查询出来:
SQL> select pct_used, height,name,lf_rows,lf_blks,del_lf_rows from index_stats;
HEIGHT NAME LF_ROWS LF_BLKS DEL_LF_ROWS
---------- ---------------------------------------------------------------------- ---------- -----------
MY_BIT_IDX 1000 3 100
分析数据分析:
(HEIGHT)这个所引高度是2 ,(NAME)索引名为MY_BIT_IDX ,(LF_ROWS)所引表有1000行数据,(LF_BLKS)占用3个块,(DEL_LF_ROWS)删除100条记录。
这里也验证了前面所说的一个问题,删除的100条数据只是标记为删除,因为总的数据条数依然为1000条,占用3个块,那么每个块大于333条记录,只有删除的数据大于333条记录,这时一个块被清空,总的数据条数才会减少。这就产生了索引碎片。(pct_used字段,如果该字段过低(低于50%),则说明存在碎片。)