数据库表索引碎片和sql性能分析

寵の児 提交于 2020-01-20 04:27:52

 

  1. 查询碎片

SELECT table_name,

         ROUND ( (blocks * 8), 2) "高水位空间 k",

         ROUND ( (num_rows * avg_row_len / 1024), 2) "真实使用空间 k",

         ROUND ( (blocks * 10 / 100) * 8, 2) "预留空间(pctfree) k",

         ROUND (

            (  blocks * 8

             - (num_rows * avg_row_len / 1024)

             - blocks * 8 * 10 / 100),

            2)

            "浪费空间 k"

    FROM user_tables

   WHERE temporary = 'N'

   and table_name in ('MAIN_TABLE1',

                                  'MAIN_TABLE2',

                                  'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

说明:如果有碎片浪费空间最好都清理一下。建议清理碎片程度计算范围

1-(真实使用空间/高水位空间)>8%

 

2、主表开启行迁移

begin

  for idx in (SELECT 'alter table ' || table_name || ' enable row movement;' row_cur

                FROM user_tables

               WHERE 

table_name in ('MAIN_TABLE1',

                        'MAIN_TABLE2',

                        'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

) loop

    begin

      execute immediate (idx.row_cur);

    EXCEPTION

      WHEN OTHERS THEN

        dbms_output.put_line(idx.row_cur);

    END;

  end loop;

end;

说明:这是批量执行开启表行迁移。在执行行迁移时,将无法进行DML操作。

 

3、收缩表空间

begin

  for idx in (SELECT 'alter table ' || table_name || ' shrink space ;' row_cur

                FROM user_tables

               WHERE 

table_name in ('MAIN_TABLE1',

                         'MAIN_TABLE2',

                         'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

) loop

    begin

      execute immediate (idx.row_cur);

    EXCEPTION

      WHEN OTHERS THEN

        dbms_output.put_line(idx.row_cur);

    END;

  end loop;

end;

说明:这是批量进行表空间收缩。对于大表收缩时间话费可能比较长,中间切勿中断。

 

4、收缩索引空间

begin

  for idx in (SELECT 'alter index' || index_name || ' shrink space ;' row_cur

                FROM user_indexes

               WHERE

table_name in ('MAIN_TABLE1',

                         'MAIN_TABLE2',

                         'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

) loop

    begin

      execute immediate (idx.row_cur);

    EXCEPTION

      WHEN OTHERS THEN

        dbms_output.put_line(idx.row_cur);

    END;

  end loop;

end;

说明:这是批量进行索引空间收缩对于大表索引收缩时间话费可能比较长,中间切勿中断。

 

 

5、主表关闭行迁移

begin

  for idx in (SELECT 'alter table ' || table_name || ' disable row movemnt;' row_cur

                FROM user_tables

               WHERE 

table_name in ('MAIN_TABLE1',

                         'MAIN_TABLE2',

                         'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

) loop

    begin

      execute immediate (idx.row_cur);

    EXCEPTION

      WHEN OTHERS THEN

        dbms_output.put_line(idx.row_cur);

    END;

  end loop;

end;

说明:关闭行迁移以后,才可以进行DML操作。切记打开以后,记得关闭行迁移。

 

6、重建表索引

begin

  for idx in (SELECT 'alter index' || index_name || ' rebuild online;' row_cur

                FROM user_indexes

               WHERE 

table_name in ('MAIN_TABLE1',

                         'MAIN_TABLE2',

                         'MAIN_TABLE3'

                                   ...)

ORDER BY 5 DESC;

) loop

    begin

      execute immediate (idx.row_cur);

    EXCEPTION

      WHEN OTHERS THEN

        dbms_output.put_line(idx.row_cur);

    END;

  end loop;

end;

说明:经过表和索引收缩以后,进行重建索引。使索引正常排列。

 

7、收集主表信息

begin dbms_stats.gather_table_stats(user,'MAIN_TABLE1',cascade=>true);end;

begin dbms_stats.gather_table_stats(user,'MAIN_TABLE2',cascade=>true);end;

begin dbms_stats.gather_table_stats(user,'MAIN_TABLE3',cascade=>true);end;

说明:这是收集主表统计信息,当索引数据准确后,需统计信息收集,使得表统计信息准确,Oracle优化器基于成本开销才能选择最优的执行路径,才能使得SQL语句执行最优执行计划,SQL性能得以提高。

 

8、SQL语句性能分析

 

1)、数据准备

Drop table test2;

 create table test2 (id number,crt_time date);

 

 begin

   for i in 1 .. 1000000 loop

     insert into test2 (id, crt_time) values (i, sysdate);

   end loop;

 end;

 

2)、性能测试--执行计划

--没加索引;

 --查询

select * from test2 where id between 123 and 77789 ;   

--执行计划

 如何查看一条SQL的执行计划?

选中查询语句,然后按F5(菜单:工具——>解释计划)

 

--增加索引

Create  unique index idx_test2_id on test2(id);

--查询

select * from test2 where id between 123 and 77789 ;  

--执行计划

 如何查看一条SQL的执行计划?

选中查询语句,然后按F5(菜单:工具——>解释计划)

 

根据耗费对比,加了索引后的SQL性能比没加索引快3倍以上。

 

9、分析表和索引的语句

 

analyze table  TABLE_NAME compute statistics 

select '  analyze index '||index_name ||' compute statistics ;' from user_indexes ui where ui.table_name='TABLE_NAME ' ;     

 

  1. 判断索引有效和无效

select ui.index_name,status  from user_indexes ui   where table_name='LIS_RESULT'      

 

说明:如果STATUS为VALID那么索引为有效。UNUSABLE为无效。

如果手工将索引 IDX_LIS_RESULT1 设为无效 可以如下操作:

alter index IDX_LIS_RESULT1 unusable; 

 

备注说明:文章中table_name是目标库查询的主表。其他小数据量的表可以不查询碎片。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!