当全库数据量较大时,按模式更新统计信息比较慢,可以使用全列收集统计信息的方式进行收集,通过存储过程完成对全库全部列的收集:
STAT < 统计信息采样百分比 > ON [< 模式名 >.]< 表名 >(< 列名 >);
如:STAT 100 ON TEST(A);
--更新指定表的所有列的统计信息可使用 SYSDBA 或者用户自身
--DROP TABLE SYSDBA.stat_history;
--SELECT * FROM SYSDBA.stat_history;
--创建日志记录表
create table SYSDBA.stat_history (beg_time TIMESTAMP,end_time timestamp,sql_str varchar2(500),table_name varchar2(200),col_name VARCHAR2(200));
--创建存储过程
CREATE OR REPLACE PROCEDURE "SYSDBA"."TABLE_STATS"
AUTHID DEFINER
AS
declare --更新所有列的统计信息
v_sql varchar(4000);
v_begtime VARCHAR2(200);
v_endtime varchar2(200);
CURSOR c1 IS SELECT
SCH.NAME AS SCHEMA_NAME,
TAB.NAME AS TABLE_NAME ,
SYSCOL.NAME AS COLUMN_NAME
FROM
SYSOBJECTS AS TAB,
SYSOBJECTS AS SCH,
SYSCOLUMNS AS SYSCOL
WHERE
SCH.ID =TAB.SCHID
AND TAB.ID =SYSCOL.ID
AND SCH.NAME in ('SYSDBA') --填写实际用户名
AND SYSCOL.TYPE$ NOT IN ('BLOB','CLOB','TEXT')
and TAB.NAME IN(select TABLE_NAME from ALL_TABLES WHERE OWNER in ('SYSDBA') and TABLE_NAME not like '%BM$_%' AND TABLE_NAME NOT LIKE 'MTAB$%');
begin
execute immediate 'truncate table SYSDBA.STAT_HISTORY;';
for i in c1
loop
v_sql='stat 100 on '||i.SCHEMA_NAME||'."'||i.TABLE_NAME||'"("'||i.COLUMN_NAME||'");';
begin
v_begtime := sysdate();
execute immediate v_sql;
v_endtime := sysdate();
insert into SYSDBA.stat_history VALUES (v_begtime,v_endtime,v_sql,i.TABLE_NAME,i.COLUMN_NAME);
commit;
EXCEPTION WHEN OTHERS THEN
PRINT SQLERRM;
end;
end loop;
end;
--调用存储过程
call "SYSDBA"."TABLE_STATS" ();
select * from SYSDBA.stat_history;
注意:使用“STAT 100 on 表名(列名)”的方法收集统计信息时,水平分区表子表采样数受 HP_STAT_SAMPLE_COUNT 参数影响。需要适当调大此参数,参数值大于实际分区数,否则分区表统计信息收集不准确,参数修改方法如下:
sp_set_para_value(1,'HP_STAT_SAMPLE_COUNT',2000);
文章
阅读量
获赞
