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;