Mostrando postagens com marcador oracle. Mostrar todas as postagens
Mostrando postagens com marcador oracle. Mostrar todas as postagens

sexta-feira, 4 de agosto de 2017

Otimizando o INSERT com FORALL - Oracle

E aí galera,
bom vamos dar um exemplo de como carregar muitos registros de uma
forma mais rápida, sem ficar sobrecarregando a área de UNDO do Oracle.
Eu preciso colocar vários clientes em atraso em uma tabela de log.



DECLARE
  /*---------------------------------------------------------------------------------*\   
  | DECLARE: ATUALIZA CLIENTES EM COBRANÇA                     |   
  | DATA CRIAÇÃO:  26/06/2005                                                             |   
  | OBJETIVO: INCLUI A CARGA DO DIA NO ESTOQUE.                |   
  | ANALISTA: GLAUBER                                                                       |   
  | Projeto: Contatos Cobrança                                                                   |   
  |==================================================|   
  | ALTERAÇÃO:                                                                                     |    
  | DATA ALTERAÇÃO:                                                                         |   
  | ANALISTA:                                                                                         |   
  \*---------------------------------------------------------------------------------*/
  
  v_QTD_UPDATE NUMBER(9) := 0;

  CURSOR c_CLIENTES_DIA IS
    SELECT DIA.ID_CONT_COBRANCA,       DIA.CPF,
           DIA.NOME,                                             DIA.STATUSREGISTRO,
           DIA.DATAULTCOMANDO,                   DIA.DATAENTCENTRAL,
           DIA.DATAATRASO,                               DIA.VALOR,
           DIA.UF,                                                    DIA.SEGMENTO,
           DIA.CDPRODLIM,                                 DIA.SUBSPID,
           DIA.COLLECTIONSCOR                      DIA.INDPARCATRASO,
           DIA.QTPARCATRASO,                         DIA.CODCAMPANHA,
           DIA.PRIORIDADE,                               DIA.VLRVAR,
           DIA.TIMEZONE,                                   DIA.CEP,
           DIA.INDQUEBRAPROMESSA,                    DIA.INDCOMPOSICAO,          
      FROM TB_CLIENTES_COBRANCA DIA
     WHERE DIA.DATAATRASO > (SYSDATE-30);
      
  --AQUI EU CRIO UMA VARIÁVEL DO TIPO ARRAY, PARA FICAR IGUAL AO CURSOR
  TYPE ARRAY IS TABLE OF c_CLIENTES_DIA%ROWTYPE INDEX BY PLS_INTEGER;
  S_ARRAY ARRAY;


BEGIN
  dbms_output.put_line('|------------------------------------------------------------|');
  dbms_output.put_line('|Início do processo:' || to_char(SYSDATE, 'dd/mm/yyy hh:mm:ss'));
  dbms_output.put_line('|------------------------------------------------------------|');

  OPEN c_CLIENTES_DIA;

  LOOP
    FETCH c_CLIENTES_DIA BULK COLLECT
      INTO S_ARRAY LIMIT 5000; --AQUI EU LIMITO UM VALOR DE 5000 CLIENTES POR EXECUÇÃO
   
   --AQUI EU FALO PRA ELE SAIR DO LOOP QUANDO NÃO RETORNAR MAIS DADOS
   EXIT WHEN S_ARRAY.COUNT = 0;

    --LEMBRANDO QUE A TABELA DESTINO DEVERÁ TER MESMOS CAMPOS QUE ESTÃO NO CURSOR.
    FORALL i IN 1 .. S_ARRAY.COUNT
      INSERT INTO TB_CONTATOS_COBRANCA_LOG VALUES S_ARRAY (i);

    -- AQUI EU CONTO A QUANTIDADE DE REGISTROS INSERIDOS
    v_QTD_INSERT := v_QTD_INSERT + SQL%ROWCOUNT;
    -- AQUI EU LIMPO A VARIÁVEL PARA SER USADA NOVAMENTE E NÃO FICAR LIXO.
    S_ARRAY.DELETE;

    COMMIT;

  END LOOP;
  CLOSE c_CLIENTES_DIA;

  COMMIT;
  dbms_output.put_line('|Quantidade de registros retornados: ' ||  v_QTD_INSERT);

  dbms_output.put_line('|------------------------------------------------------------|');
  dbms_output.put_line('|Fim do processo:' || to_char(SYSDATE, 'dd/mm/yyyy hh:mm:ss'));
  dbms_output.put_line('|------------------------------------------------------------|');

EXCEPTION
  WHEN OTHERS THEN
    dbms_output.put_line('|------------------------------------------------------------|');
    dbms_output.put_line('| MENSAGEM ORACLE : ' || SQLERRM);
    dbms_output.put_line('|------------------------------------------------------------|');
    dbms_output.put_line('|Fim do processo:' || to_char(SYSDATE, 'dd/mm/yyyy hh:mm:ss'));
    dbms_output.put_line('|------------------------------------------------------------|');
END;


Blz galera, esse é um exemplo fácil para você criar um insert em lote, vlw
qualquer dúvida só postar nos comentários.


segunda-feira, 30 de maio de 2016

Utilizando Hint's para performance das query's.

Olá galera, Vamos ver alguns Hint's que podem nos ajudar em nossas consultas. Muitas pessoas não gostam de utilizar, outras utilizam sempre, mas sempre é bom analisar sua query pra saber se irá otimizar seu tempo de resposta ou piora-lo. Pois é preciso conhecer e analisar, o que será melhor para o Oracle.

Temos vários hint's, "sugestões" algumas já obsoletas, mas vários que podem nos ajudar... eles são declarados como comentários.

Como por exemplo o first_rows, já me ajudou, mas é preciso fazer consultas analisando sua query, também com explan para verificar como o Oracle se comporta, esse hint ele força o uso de índice, para otimizador um caminho que retorna a 1º linha ou a quantidade de linhas que escolher mais rapidamente.

Exemplo:
select /*+ first_rows (500) */ coluna_1, coluna_2 from tabela;


O hint /*+ full_rows (tabela) */ força um scan completo na tabela, custo do acesso do índice e dos registros pode ser maior do que simplesmente ler a tabela inteira. Este hint também pode causar resultados inesperados, como varrer a tabela interia em ordem diferente da ordem de acesso, se for uma tabela com centenas de dados, não é aconselhável.

Exemplo:
select /*+ full_rows (tabela_user) */ coluna_1, coluna_2 from tabela_user where rownum <= 10;



A partir do Oracle 11g, temos uma view com mais de 250 Hint's v$sql_hint, se fosse de todo mau, não existiria mais.

Existem vários outros HINT's, mas entenda, sempre é bom se aprofundar no conhecimento, pois não têm uma receita de bolo, e sim uma melhor prática para cada caso. Vlw galera, qualquer dúvida é só compartilhar.

Referências: https://community.oracle.com/welcome