Social Icons

8 de set. de 2026

Eliminando chained rows para otimizar SQLs




Olá pessoal,

     No post de hoje vou mostrar como eliminar "chained rows" ou linhas encadeadas e migradas (LEMs) em uma tabela, visando otimizar a performance de SQLs que executam queries nela, usando como exemplo, um caso real em que atuei faz alguns anos. Se você é novo no mundo Oracle ou tem pouca experiência com tuning, e não sabe muito bem o que são chained rows ou LEMs, sugiro a leitura prévia do artigo Desfragmentando tabelas no Oracle.


     O caso citado em que atuei consistia analisar uma query que um DEV reclamou de performance em um banco de dados produção. A query consultava a tabela TAB_TESTE (nome fictício) e ao consultá-la na view DBA_TABLES, após executar o comando ANALYZE TABLE TAB_TESTE COMPUTE STATISTICS, obtive as seguintes estatísticas:
         - Qtde. de linhas (NUM_ROWS): 768.545
         - Qtde. de blocos (BLOCKS) 22.592
         - Qtde. de bloco vazios (EMPTY_BLOCKS): 192
         - Qtde. de LEMs (CHAIN_CNT): 470.219
         - Qtde. média de linhas por bloco (AVG_ROW_LEN) = 194
 
ATENÇÃOÉ importante ressaltar que o comando ANALYZE TABLE foi executado apenas para obter os valores de EMPTY_BLOCKS e CHAIN_CNT. Não execute-o com o objetivo de atualizar estatísticas de objetos visando otimizar SQLs. Para saber mais sobre este assunto sugiro a leitura do artigo Coletando estatísticas para o otimizador de queries do Oracle.

     Conforme as estatísticas apresentadas acima, podemos verificar que existem 192 blocos vazios e 470.219 LEMs na tabela. A quantidade de LEMs é bem grande e isso impacta negativamente na performance não apenas de queries na tabela, mas também na execução de exports e backups, então é necessário investigar o porquê das LEMs terem surgido, tentar evitá-las, e criar alguma rotina de manutenção na tabela com o objetivo de eliminá-las. Em geral, o mínimo que um DBA deve fazer é criar uma rotina de manutenção para eliminá-las. Eu já fiz isso diversas vezes (sempre que necessário), e vou mostrar ao longo deste artigo como executo este procedimento.  
 
    Entre as diversas formas de eliminar LEMs, citarei abaixo as principais:
          1- Usando a package DBMS_REDEFINITION;
          2- Executando CTAS+ rename table;
          3- Executando ALTER TABLE MOVE (dentro do mesmo tablespace) ou movendo dados da tabela para outro tablespace e retornando-os dados em seguida para o tablespace original;
          4- Fazendo export, TRUNCATE, import;
          5- Reinserindo as LEMs usando ANALYZE TABLE CHAINED ROWS.

     A última opção (item 5) é a que irei explicar a seguir, e que sempre executo, por ser o procedimento mais rápido de executar, mais fácil de ser automatizado, e que gera o menor impacto no ambiente, ocasionando indisponibilidade temporária mínima apenas nas LEMs (e não na tabela inteira)

     O procedimento consiste nos seguintes passos:

1) Criar a tabela CHAINED_ROWS:
Para iniciar o procedimento é necessário criar a tabela CHAINED_ROWS, executando o script oficial fornecido pela Oracle, chamado utlchain.sql. Esse script, que está incluso em qualquer instalação do banco de dados, cria a tabela CHAINED_ROWS com a estrutura exata necessária para armazenar as LEMs. Você deve executar este script uma única vez no banco de dados.

2) Executar ANALYZE TABLE CHAINED_ROWS para identificar LEMs:
Agora você deve executar o comando abaixo para que ele identifique as LEMs dentro da tabela origem e grave as referências dessas linhas na tabela CHAINED_ROWS, criada no passo anterior:
SQL>  ANALYZE TABLE TAB_TESTE LIST CHAINED ROWS INTO CHAINED_ROWS;

3) Salvar LEMs em uma tabela clone temporária:
Neste passo você vai criar uma tabela auxiliar clone da tabela TAB_TESTE, chamada AUX_CHAINED, que deverá conter somente as LEMs que foram gravadas na tabela CHAINED_ROWS, no passo anterior:
 SQL>  create table AUX_CHAINED as
      select * from TAB_TESTE
      where rowid in (select head_rowid 
                      from   CHAINED_ROWS
                      where table_name = 'TAB_TESTE');
                    

4) Deletar as LEMs na tabela original:
Após gravarmos no passo anterior os dados das LEMs (que inclui o rowid delas) na tabela auxiliar clone, podemos apagar as linhas correspondentes na tabela original:
 SQL>  delete from TAB_TESTE
      where rowid in 
(select head_rowid 
                      from   CHAINED_ROWS
                      where table_name = 'TAB_TESTE');

5) Reinserir as LEMs na tabela original:
Chegamos ao passo final, que consiste em reinserir as LEMs na tabela original a partir das linhas que foram gravadas na tabela auxiliar clone. Para fazer isso execute o SQL abaixo:
SQL> insert into TAB_TESTE
     select * from AUX_CHAINED;
     commit;


     Pronto, neste momento você eliminou todas ou grande parte da LEMs na tabela TAB_TESTE. Para verificar isso eu executei novamente o comando ANALYZE TABLE TAB_TESTE COMPUTE STATISTICS e o obtive em seguida as seguintes estatísticas:
         - Qtde. de linhas (NUM_ROWS): 768.545
         - Qtde. de blocos (BLOCKS): 21.363
         - Qtde. de bloco vazios (EMPTY_BLOCKS): 189
         - Qtde. de LEMs (CHAIN_CNT):
         - Qtde. média de linhas por bloco (AVG_ROW_LEN) = 191

   Podemos observar agora que diversos valores diminuíram um pouco, tais como: BLOCKS, EMPTY_BLOCKS e AVG_ROW_LEN; mas a principal diferença foi a redução de LEMs (CHAIN_CNT), que caiu de 470.219 para 0, ou seja, não temos mais LEMs na tabela

Observação: 
Após finalizar o procedimento de eliminação de LEMs apresentado acima, sugiro executar os comandos abaixo para diminuir o tamanho da tabela e coletar estatísticas da tabela com o package DBMS_STATS:
SQL>  ALTER TABLE TAB_TESTE enable row movement;              
      ALTER TABLE TAB_TESTE SHRINK SPACE;
      exec dbms_stats.gather_table_stats(
USER,'TAB_TESTE'); -- substitua USER pelo owner da tabela.


Se você é DBA e não conhecia o procedimento que apresentei acima, tenho certeza de que no futuro ele lhe será muito útil!

Caso queira aprender mais sobre o assunto sugiro participar comigo na próxima turma do treinamento Oracle Database Performance Tuning da Oramaster.


Por hoje é só!
[ ] s
Fábio Prado

0 comments:

Postar um comentário

 

LINKS ÚTEIS

Total de visualizações de página

Seguidores

Meu One Drive (antigo Sky Drive)