2013-08-05


----------------索引的重建--------------------

什么情况下需要重建索引?


alter index index_name rebuild;  ——当索引很大的时候,会执行很长时间,严重影响性能。


1、如果B树索引失效了是必须要重建的。


2、如果没有失效,怎样判断需要重建:

当索引占用空间超过了一个数据块,且符合下面任何一个条件的时候:


A、 B-TREE的高度大于3

B、 数据删除率大于20%

C、 索引可使用的百分比小于75%


SQL> create index ind_obj_id on tt1(object_id);


Index created.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

207928          2         87           0%



SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> commit;


Commit complete.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> commit;


Commit complete.


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   1671196          2         90 0%



删除数据:


SQL> delete from tt1 where rownum<=100000;


93519 rows deleted.


SQL> rollback;


Rollback complete.


SQL> delete from tt1 where rownum<=60000;


60000 rows deleted.


SQL> delete from tt1 where rownum<=10000;


10000 rows deleted.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

1671196         2         90    74.8510997765160020958307937424480586833%


重建索引:

SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

431816             2         88     0%


pct free = 10%


插入数据:


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> commit;


Commit complete.


SQL> insert into tt1 select * from tt1;


229384 rows created.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

11106604           3       66          0%


说明刚才插入的值有24%的索引空间是没有生效的,索引键值没有生效。


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8164012     3         90          0%



少量插入数据:

SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> commit;


Commit complete.


SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8252000       3         89         0%


SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> commit;


Commit complete.


SQL> insert into tt1 select * from tt1 where rownum<=500;


500 rows created.


SQL> commit;


Commit complete.


SQL> insert into tt1 select * from tt1 where rownum<=1000;


1000 rows created.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8299976          3         89 0%


插入少量数据的时候,索引会自动维护的。



update操作是否也会影响索引:

SQL> update tt1 set object_id=object_id+1;


461768 rows updated.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

  16599888       3        67      33.4890835606691306314221762589409944777%


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8219984      3         90          0%




update少量的数据:


SQL> update tt1 set object_id=object_id+1 where rownum<=500;


500 rows updated.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8219984          3         90 .108162364688881774208900464665518703436%



SQL> update tt1 set object_id=object_id+1 where rownum<=1000;


1000 rows updated.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.



SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   8219984          3         90 .216091000242021920271064550703592296788%







---结果:说明update操作队索引基本无影响,可以自动去维护。--


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

问题:

按照需求要求表上要创建索引,但是表是空表,先插入数据在创建索引性能好高?

是先创建索引再插入数据性能高?(先插入数据再建索引好)


实验测试:

先创建索引:

SQL> truncate table tt1;


Table truncated.


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> insert into tt1 select * from all_objects;  大批量插入数据


41173 rows created.


SQL> commit;


Commit complete.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   1247408          2         53 0%    --索引不会自动维护的。


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

    743660          2         89 0%


插入少量数据也是这样的结果。而且数据量非常少的时候,即使重建了索引,pct_used也达不到90%,

也就是说数据量很小的话,没有必要作这种检查,数据量小即使全表扫表也问题不大。


检查这几个指标的时候要找到50000条数据以上的表才有意义。


结论:当空表中插入大量数据的时候,索引会失效的,所以应该是先插入数据再创建索引。


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

先删除20000条数据,再插入20000条数据,碎片空间会不会被重用?包括表和索引的,

如果能被重用,索引是否会有影响?


SQL> truncate table tt1;


Table truncated.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> insert into tt1 select * from all_objects;


41173 rows created.


SQL> commit;


Commit complete.


SQL> alter index ind_obj_id rebuild;


Index altered.


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   2198932          2         90   0%


SQL> select count(1) from user_extents where segment_name='IND_OBJ_ID';


 COUNT(1)

----------

       18


SQL> select count(1) from user_extents where segment_name='TT1';


 COUNT(1)

----------

       29


SQL> insert into tt1 select * from all_objects  where rownum<=20000;


20000 rows created.


SQL> commit;


Commit complete.


SQL> select count(1) from user_extents where segment_name='TT1';   --都没有在HWM之上去开辟空间,碎片能被重用。


 COUNT(1)

----------

       29


SQL> select count(1) from user_extents where segment_name='IND_OBJ_ID';


 COUNT(1)

----------

18


SQL> analyze index ind_obj_id validate structure;


Index analyzed.


SQL> select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


BTREE_SPACE     HEIGHT   PCT_USED DELETE_PCT

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

   2262900      2         88      .740115718418514946962391513982642237223%


加大数据量操作也是这样的效果。


操作                          索引是否会失效         索引是否会自动维护

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

move操作                          会                   不会

shrink操作                       不会                  不会

少量的insert操作                 不会                   会

大量的insert操作                 不会                  不会

少量的update操作                 不会                   会

大量的update操作                 不会                  不会

delete操作                       不会                  不会

truncate操作                     不会                   会

空表中插入大量数据               不会                   不会

删除数据后插入同样的数据         不会                   会

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


索引的监控和维护是数据库最为难最为麻烦的工作,关键是要求不停的监控,而且修复,

修复的过程中rebuild对于大表时间会很久,历来DBA工作的难点。



index_stats——这个视图是创建在提示表空间上的会话级别的视图,查看之前必须要先分析索引和表数据的对应性,在当前会话查询才能查到值。

analyze index ind_obj_id validate structure;

select btree_space,height,pct_used,(del_lf_rows/decode(lf_rows,0,1,lf_rows))*100||'%' as delete_pct from index_stats;


查询索引的基本信息:

select * from user_indexes where index_name='IND_OBJ_ID'

如果上面的视图和select * from index_stats;查询的结果有些相同指标值不一样的话,说明这个索引没有分析,执行分析之后就可以了。


创建索引的时候指定表空间,比如将表数据和索引数据分两个磁盘存储,这样在读取的时候就能分摊IO的压力。企业部署用不同的磁盘存储索引,这样IO分摊,访问速度就会很快。

create index xxxx on tb_name(column_name) tablespace xxxxxx;


create index ind_obj_id on tt1(object_id) tablespace mytbs3;