As estatísticas podem ficar obsoletas quando os dados na tabela mudam substancialmente. Estatísticas atualizadas são importantes para gerar bons planos de execução
Como a Oracle decide se as estatísticas se tornaram obsoletas
As estatísticas são consideradas obsoletas quando #(INSERTS + UPDATES + DELETES)>=10% de NUM_ROWS de dba_tables:
Configuração de parâmetro necessária para acompanhar as alterações da tabela
Antes do Oracle 10g, a coleta automatizada de estatísticas para objetos que se tornaram obsoletos era controlada pela configuração do sinalizador MONITORING na tabela.
Dependendo do sinalizador MONITORING, o trabalho GATHER_STATS_JOB coletava “GATHER EMPTY” e “GATHER STALE” nos objetos sinalizados.
Em 10g, as palavras-chave MONITORING e NOMONITORING estão obsoletas e serão ignoradas. O recurso de monitoramento de tabela agora é controlado pelo parâmetro STATISTICS_LEVEL.
Quando STATISTICS_LEVEL é configurado como BASIC, o monitoramento é desabilitado na tabela.
Quando STATISTICS_LEVEL é configurado como TYPICAL, então o monitoramento é habilitado.
Por padrão, STATISTICS_LEVEL é configurado como TYPICAL e o monitoramento de tabelas é habilitado. É altamente recomendável definir STATISTICS_LEVEL como TYPICAL em 10g e acima
Ao definir esses parâmetros, o Oracle rastreia o número aproximado de operações INSERT, UPDATE e DELETE para a tabela do Oracle desde a última vez em que as estatísticas foram coletadas. Essas informações sobre “alterações feitas” são mantidas no SGA e periodicamente (a cada 15 minutos) o SMON libera os dados nas tabelas do dicionário de dados. Você pode liberar manualmente as informações chamando dbms_stats.FLUSH_DATABASE_MONITORING_INFO(). As informações do dicionário de dados ficam visíveis através das visualizações:DBA_TAB_MODIFICATIONS, ALL_TAB_MODIFICATIONS e USER_TAB_MODIFICATIONS.
A Oracle usa essas visualizações para identificar tabelas que possuem estatísticas obsoletas.
Sempre que houver 10% de alteração nos dados em uma tabela, a Oracle considera suas estatísticas obsoletas.
Como verificar estatísticas obsoletas
O procedimento PLSQL abaixo descobre todas as tabelas no esquema SCOTT, que são estatísticas obsoletas
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(ownname=>'SCOTT', objlist=>ObjList, options=>'LIST STALE'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
O sql abaixo também pode ser usado para descobrir inserir, atualizar, excluir
select u.TIMESTAMP, t.last_analyzed, u.table_name, u.inserts, u.updates, u.deletes, d.num_rows, decode(d.num_rows,0,'Table Stats indicate No Rows', nvl(TO_CHAR(((U.inserts+u.deletes+u.updates)/d.num_rows) * 100,'999.99') ,'Null Value in USER_TAB_MODIFICATIONS') ) percent from user_tables t,USER_TAB_MODIFICATIONS u,dba_tables d where u.table_name = t.table_name and d.table_name = t.table_name and d.owner = '&Owner' and (u.inserts > 3000 or u.updates > 3000 or u.deletes > 3000) order by t.last_analyzed /
Se você quiser executar isso no banco de dados inteiro
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_DATABASE_STATS(objlist=>ObjList, options=>'LIST STALE'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
Se você quiser ver as tabelas onde as estatísticas estão vazias, podemos usar abaixo
SET SERVEROUTPUT ON SQL> DECLARE ObjList dbms_stats.ObjectTab; BEGIN DBMS_STATS.GATHER_DATABASE_STATS(objlist=>ObjList, options=>'LIST EMPTY'); FOR k in ObjList.FIRST..ObjList.LAST LOOP dbms_output.put_line(ObjList(k).ownname || '.' || ObjList(k).ObjName || ' ' || ObjList(k).ObjType || ' ' || ObjList(k).partname); END LOOP; END; /
Agora, depois de encontrar a lista de tabelas, você pode gerar estatísticas sobre essas tabelas.
exec dbms_stats.gather_table_stats('OWNER', 'TABLE_NAME');
Também podemos executar o comando abaixo para gerar estatísticas em todo o objeto obsoleto no esquema
exec dbms_stats.gather_schema_stats(ownname => '<schema name>', cascade => TRUE, options => 'GATHER AUTO');
A partir do Oracle11g, o limite de inatividade pode ser definido usando a preferência de estatísticas STALE_PERCENT. Isso pode ser definido globalmente usando DBMS_STATS.SET_GLOBAL_PREFS ou no nível da tabela usando DBMS_STATS.SET_TABLE_PREFS.
Artigos relacionados
ora-38029:as estatísticas do objeto estão bloqueadas
ora-20001 em Reunir estatísticas de esquema em 11g(FND_HISTOGRAM_COLS)
Reunir estatísticas na versão 11i e R12
Reunir estatísticas incrementais em 11g
Como definir Monitoramento de Tabela no Oracle e Relacionamento com STATISTICS_LEVEL