Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

O que há de errado com os cursores?


O que há de errado com os cursores é que eles são frequentemente abusados, tanto no Oracle e em MS SQL .

O cursor serve para manter um conjunto de resultados estável que você pode recuperar linha por linha. Eles são criados implicitamente quando sua consulta é executada e fechados quando ela é concluída.

É claro que manter tal conjunto de resultados requer alguns recursos:locks , latches , memory , até mesmo disk space .

Quanto mais rápido esses recursos forem liberados, melhor.

Manter um cursor aberto é como manter a porta de uma geladeira aberta

Você não faz isso por horas sem necessidade, mas isso não significa que você nunca deve abrir sua geladeira.

Isso significa que:
  • Você não obtém seus resultados linha por linha e os soma:você chama o SQL 's SUM em vez disso.
  • Você não executa a consulta inteira e obtém os primeiros resultados do cursor:você anexa um rownum <= 10 condição para sua consulta

, etc

Quanto ao Oracle , processar seus cursores dentro de um procedimento requer a infame SQL/PLSQL context switch que acontece toda vez que você obtém um resultado de um SQL consulta fora do cursor.

Envolve passar grandes quantidades de dados entre threads e sincronizar os threads.

Esta é uma das coisas mais irritantes no Oracle .

Uma das consequências menos evidentes desse comportamento é que os gatilhos no Oracle devem ser evitados, se possível.

Criando um gatilho e chamando um DML A função é igual a abrir o cursor selecionando as linhas atualizadas e chamando o código de trigger para cada linha deste cursor.

A mera existência do gatilho (mesmo o gatilho vazio) pode retardar um DML operação 10 times ou mais.

Um script de teste em 10g :
SQL> CREATE TABLE trigger_test (id INT NOT NULL)
  2  /

Table created

Executed in 0,031 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 1,469 seconds
SQL> COMMIT
  2  /

Commit complete

Executed in 0 seconds
SQL> TRUNCATE TABLE trigger_test
  2  /

Table truncated

Executed in 3 seconds
SQL> CREATE TRIGGER trg_test_ai
  2  AFTER INSERT
  3  ON trigger_test
  4  FOR EACH ROW
  5  BEGIN
  6     NULL;
  7  END;
  8  /

Trigger created

Executed in 0,094 seconds
SQL> INSERT
  2  INTO   trigger_test
  3  SELECT level
  4  FROM   dual
  5  CONNECT BY
  6     level <= 1000000
  7  /

1000000 rows inserted

Executed in 17,578 seconds

1.47 segundos sem um acionador, 17.57 segundos com um gatilho vazio sem fazer nada.