Pular para o conteúdo

Monitoramento de modificações nas tabelas do Oracle – Saiba como manter suas estatísticas atualizadas

Monitoramento de modificações nas tabelas do Oracle

Sabe aquela conta que o Oracle faz para saber quando as estatísticas estão desatualizadas? Então, você pode fazer a mesma conta consultando a view dba_tab_modifications. Por padrão quando uma tabela sofre 10% de alteração o Oracle considera que suas estatísticas estão desatualizadas, então se você usa a dbms_stats.gather_stats com OPTIONS=>’GATHER STALE’ as estatísticas serão coletadas depois dessa quantidade de alterações. Você pode mudar o percentual de Stale Statistics com a procedure dbms_stats.set_prefs e o parâmetro STALE_PERCENT.

A versão do meu Oracle é 12.1.0.2, mas tudo isso funciona igual para as versões do Oracle Database 11g e 10g (acredito que funciona também no 9i, mas acho que não existe somente a procedure flush_database_monitoring_info, não cheguei a testar).

Vamos aos exemplos e testes…

Vou criar primeiro uma tabela de testes.

SQL> create table t as select * from hr.jobs;

Table created.

Vamos verificar como essa tabela é criada por default.

SQL> SET PAGES 200 LIN 200
SQL> COL OWNER FOR A20
SQL> COL TABLE_NAME FOR A30
SQL> select owner, table_name, monitoring, num_rows, blocks, empty_blocks, 
avg_space, to_char(last_analyzed, 'dd/mm/yyyy hh24:mi:ss') last_analyzed
from dba_tables
where owner='SYS' and table_name='T';

OWNER                TABLE_NAME                     MON NUM_ROWS   BLOCKS     EMPTY_BLOCKS AVG_SPACE  LAST_ANALYZED
-------------------- ------------------------------ --- ---------- ---------- ------------ ---------- -------------------
SYS                  T                              YES

Veja que a tabela já é criada com o monitoramento habilitado, isso se deve porque o parâmetro statistics_level do meu banco de dados está com o valor TYPICAL. A mesma coisa acontece se o parâmetro estiver como ALL, o monitoramento só não será habilitado por default se a tabela for criada quando o parâmetro em questão estiver definido como BASIC. (Veja detalhes no tópico 13.3.1.8 do Performance Tuning Guide)

É importante saber como desabilitar e habilitar o monitoramento nas tabelas.

Para desabilitar:

SQL> alter table T nomonitoring;

Table altered.

Então verificamos se foi desabilitado:

SQL> select owner, table_name, monitoring 
from dba_tables 
where owner='SYS' 
and table_name='T';

OWNER                TABLE_NAME                     MON
-------------------- ------------------------------ ---
SYS                  T                              NO

Agora vamos habilitar novamente:

SQL> alter table T monitoring;

Table altered.

Agora constatamos que a tabela está sendo novamente monitorada:

SQL> select owner, table_name, monitoring 
from dba_tables 
where owner='SYS' 
and table_name='T';

OWNER                TABLE_NAME                     MON
-------------------- ------------------------------ ---
SYS                  T                              YES

Vamos verificar se nossa tabela já possui alguma alteração:

SQL> select table_name,inserts,updates,deletes,truncated,timestamp
from dba_tab_modifications
where table_name='T';

no rows selected

Vamos inserir alguns registros, realizar algumas alterações e exclusões dessa tabela para observarmos o resultado do monitoramento.

SQL> insert into t values ('OP_MGR', 'Operations Manager', 10000, 20000);

1 row created.

SQL> insert into t values ('BD_MEM', 'Board Member', 100000, 500000);

1 row created.

SQL> insert into t values ('IT_MGR', 'IT Manager', 10000, 30000);

1 row created.

SQL> update t set max_salary=35000 where job_id='IT_MGR';

1 row updated.

SQL> update t set max_salary=50000 where job_id='OP_MGR';

1 row updated.

SQL> update t set max_salary=900000 where job_id='BD_MEM';

1 row updated.

SQL> delete t where job_id='BD_MEM';

1 row deleted.

SQL> commit;

Commit complete.

Vamos verificar se as alterações foram gravadas pelo monitoramento da tabela:

SQL> select table_name,inserts,updates,deletes,truncated,timestamp
from dba_tab_modifications
where table_name='T';

no rows selected

Ué, onde estão as alterações feitas na tabela T?

Nem sempre essa informação vai imediatamente para as tabelas, então é necessário descarregá-las da área de memória da instância Oracle para as tabelas utilizando a procedure dbms_stats.flush_database_monitoring_info.

SQL> exec dbms_stats.flush_database_monitoring_info;

PL/SQL procedure successfully completed.

Agora sim podemos ver as alterações que a tabela T sofreu.

SQL> select table_name,inserts,updates,deletes,truncated,timestamp
from dba_tab_modifications
where table_name='T';

TABLE_NAME                     INSERTS    UPDATES    DELETES    TRU TIMESTAMP
------------------------------ ---------- ---------- ---------- --- ---------
T                              3          3          1          NO  10-SEP-16

Observamos que ao coletar estatísticas da tabela as informações de monitoramento são excluídas.

SQL> exec dbms_stats.gather_table_stats('SYS','T');

PL/SQL procedure successfully completed.

SQL>  select table_name,inserts,updates,deletes,truncated,timestamp
from dba_tab_modifications
where table_name='T';

no rows selected

A descarga das informações da memória para as tabelas é feita em diferentes intervalos/momentos dependendo de cada versão. No Oracle 9i li em algum lugar que as informações são descarregadas a cada 15 minutos, no 10g a cada 3 horas, mas acho que nas versões atuais, 11g e 12c, esse intervalo não vale mais, pelo que consegui validar a descarga acontece quando o buffer fica cheio. Quando eu achar a referência atualizo o artigo, porque acredito que li isso em algum livro.

Este é um entendimento bastante simples, mas interessante sobre os comportamentos do banco de dados Oracle.

Já usei este tipo de procedimento apresentado no artigo até como um tipo trace de sessões vindas de um servidor de aplicação com Tomcat para poder saber as tabelas que estavam sendo alteradas por um determinado processo do sistema. Nesse cenário somente um usuário estava trabalhando no sistema, mas como não era possível isolar a sessão foi a única maneira que consegui para identificar algo do que estava sendo feito pelo sistema e isso ajudou o desenvolvedor a corrigir o código.

Espero que seja útil para vocês e se gostaram curtam e compartilhem para difundir o conhecimento na comunidade.

Como dica de teste sugiro você criar uma tabela de exemplo e realizar 11% de alteração nela e então coletar estatísticas com a opção Gather Stale para validar o que falei, você verá que realmente funciona e saberá como o Oracle calcula as estatísticas desatualizadas.

Referências

Abraço

Franky Weber Faust

Franky Weber Faust

atua como consultor Oracle, MySQL e SQL Server na NVL IT Agility onde presta serviços para grandes empresas da região sul, tem 25 anos, é graduado em Tecnologia em Bancos de Dados e iniciou sua carreira trabalhando num projeto internacional da Volkswagen com os bancos de dados DB2 da IBM, SQL Server da Microsoft e também com o Oracle e desde o início direcionou seus estudos para as tecnologias Oracle. É especialista em tecnologias de Alta Disponibilidade como RAC, Dataguard e GoldenGate e compartilha seus conhecimentos no blog loredata.com.br. Possui as certificações OCE SQL, OCA 11g, OCP 12c e OCS Linux 6.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Marcações:
plugins premium WordPress