oracle表分析

sql 代码
ORACLE9以后如果你想用基于成本的优化器,需要定期(每周)对数据库里的表和索引做analyze分析。   
    
  数据库参数文件initorasid.ora里默认的优化器 optimizer_mode= choose   
      
   你要改成 optimizer_mode =first_rows (OLTP系统)   
     optimizer_mode =all_rows (DSS 系统)   
      
   下面是一个可以在UNIX环境自动生成分析表和索引的脚本analyze.sh   
      
   (sys用户的密码password要根据情况修改。)   
      
---------------------------------------------------------------------------------------            
su - oracle -c "sqlplussys/password"<
    
set pages 9999   
set heading off  
set echo off  
set feedback off  
    
spool /oracle_backup/bin/analyze.sql;   
    
select  
'analyze table '||owner||'.'||table_name||'estimate statistics sample 5000 rows;'   
from dba_tables   
where owner not in('SYS','SYSTEM','PERFSTAT');   
  
select  
'analyze index '||owner||'.'||index_name||'compute statistics;'   
from dba_indexes   
where owner not in('SYS','SYSTEM','PERFSTAT');   
  
spool off;   
  
set echo on  
set feedback on  
spool /oracle_backup/log/analyze.log;   
@/oracle_backup/bin/analyze.sql   
spool off;   
exit;   
---------------------------------------------------------------------------------------    
  
   如果你经常变动的表和索引只属于某个特定的用户(如果是test)可以把上面的   
      
    owner not in('SYS','SYSTEM','PERFSTAT') 改成   
    owner in('TEST')      
      
   来进行定期的分析。   
      
   注意事项:如果你使用的是默认的优化器(choose),一定不要定期使用上面那个analyze.sh脚本。   
         因为这时优化器可能更倾向于全表扫描。   
      
   如果统计分析资料不全,SQL运行时会对缺少统计资料的表进行数据采集。会大大降低SQL的执行速度。   
      
   我们要用下面这个del_analyze.sh脚本定期删除可能产生的分析结果,保证优化器按规则(rule)执行。   
      
---------------------------------------------------------------------------------------            
su - oracle -c "sqlplussys/password"<
  
set pagesize9999;   
set linesize 120;   
set heading off;   
set echo off;   
set feedback off;   
  
spool/oracle_backup/bin/del_analyze.sql;   
  
select  
'analyze table '||owner||'.'||table_name||'delete statistics;'   
from dba_tables   
where owner not in('SYS','SYSTEM','PERFSTAT');   
  
select  
'analyze index '||owner||'.'||index_name||'delete statistics;'   
from dba_indexes   
where owner not in('SYS','SYSTEM','PERFSTAT');   
  
spool off;   
  
set echo on;   
set feedback on;   
spool /oracle_backup/log/del_analyze.log;   
@/oracle_backup/bin/del_analyze.sql   
spool off;   
exit;   
---------------------------------------------------------------------------------------  




在使用DBMS_STATS分析表的时候,我们经常要保存之前的分析,以防分析后导致系统性能低下然后进行快速恢复。
首先创建一个分析表,该表是用来保存之前的分析值。
SQL> begin
   2   dbms_stats.create_stat_table(ownname => 'TEST',stattab => 'STAT_TABLE');
   3   end;
   4   /
PL/SQL 过程已成功完成。
分析表信息
SQL> BEGIN
   2   --DBMS_STATS.delete_table_stats(ownname => 'TEST',tabname => 'A');
   3   DBMS_STATS.gather_table_stats(ownname => 'TEST',tabname => 'A');
   4   END;
   5   /
PL/SQL 过程已成功完成。
导出表分析信息到stat_table中。
SQL> BEGIN
   2   dbms_stats.export_table_stats(ownname => 'TEST',tabname => 'A',stattab => 'STAT_TABLE');
   3   END;
   4   /
PL/SQL 过程已成功完成。
SQL>
同理也有
EXPORT_COLUMN_STATS:导出列的分析信息
EXPORT_INDEX_STATS:导出索引分析信息
EXPORT_SYSTEM_STATS:导出系统分析信息
EXPORT_TABLE_STATS:导出表分析信息
EXPORT_SCHEMA_STATS:导出方案分析信息
EXPORT_DATABASE_STATS:导出数据库分析信息
IMPORT_COLUMN_STATS:导入列分析信息
IMPORT_INDEX_STATS:导入索引分析信息
IMPORT_SYSTEM_STATS:导入系统分析信息
IMPORT_TABLE_STATS:导入表分析信息
IMPORT_SCHEMA_STATS:导入方案分析信息
IMPORT_DATABASE_STATS:导入数据库分析信息
GATHER_INDEX_STATS:分析索引信息
GATHER_TABLE_STATS:分析表信息,当cascade为true时,分析表、列(索引)信息
GATHER_SCHEMA_STATS:分析方案信息
GATHER_DATABASE_STATS:分析数据库信息
GATHER_SYSTEM_STATS:分析系统信息
SQL> select count(*) from stat_table;
   COUNT(*)
----------
          1
删除分析信息
SQL> BEGIN
   2   DBMS_STATS.delete_table_stats(ownname => 'TEST',tabname => 'A');
   3   END;
   4   /
PL/SQL 过程已成功完成。
导入分析信息
SQL> BEGIN
   2   DBMS_STATS.import_table_stats(ownname => 'TEST',tabname => 'A',stattab => 'STAT_TABLE');
   3   END;
   4   /
PL/SQL 过程已成功完成。
SQL>示例:--analyze.sqlset serveroutput on size 100000
declare
v_per number(3);
v_start number := dbms_utility.get_time;
v_end   number;
beginfor rec in (select segment_name,segment_type,ceil(sum(bytes)/1024/1024) segment_size
from user_segments group by segment_name,segment_type)
loop    if rec.segment_type = 'INDEX' then
         dbms_stats.gather_index_stats(ownname=>'citictest', --自己改一下
                                       INDNAME=>rec.segment_name
                                      );--        dbms_output.put_line(rec.segment_name||' '||rec.segment_size||'m '||ceil((dbms_utility.get_time - v_start)/100)||'s');
         v_start := dbms_utility.get_time;    elsif rec.segment_type = 'TABLE' then
        case when rec.segment_size < 32 then
            v_per := 100;
             when rec.segment_size < 320 then
            v_per := 10;
        else
            v_per := 1;
        end case;
             dbms_stats.gather_table_stats(OWNNAME=>'citictest',
                   TABNAME=>rec.segment_name,
                   ESTIMATE_PERCENT=>v_per,
                   METHOD_OPT=>'FOR ALL INDEXED COLUMNS');--         dbms_output.put_line(rec.segment_name||' '||rec.segment_size||'m '||ceil((dbms_utility.get_time - v_start)/100)||'s');
         v_start := dbms_utility.get_time;    end if;
end loop;
end;
/  

你可能感兴趣的:(oracle,sql,unix,脚本)