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

Considerações de desempenho para dados temporários no Oracle


As tabelas temporárias são efetivamente iguais às tabelas na memória graças ao armazenamento em cache e E/S assíncrona, e a solução de tabela temporária não requer nenhuma sobrecarga para a conversão entre SQL e PL/SQL.

Confirmar os resultados

Comparando as duas versões com RunStats, a versão da tabela temporária parece muito pior. Todo aquele lixo para a versão de tabela temporária em Run1, e apenas um pouco de memória extra para a versão PL/SQL em Run2. A princípio, parece que o PL/SQL deve ser o vencedor.
Type  Name                              Run1 (temp) Run2 (PLSQL)         Diff
----- -------------------------------- ------------ ------------ ------------
...
STAT  physical read bytes                    81,920            0      -81,920
STAT  physical read total bytes              81,920            0      -81,920
LATCH cache buffers chains                  104,663          462     -104,201
STAT  session uga memory                    445,488      681,016      235,528
STAT  KTFB alloc space (block)            2,097,152            0   -2,097,152
STAT  undo change vector size             2,350,188            0   -2,350,188
STAT  redo size                           2,804,516            0   -2,804,516
STAT  temp space allocated (bytes)       12,582,912            0  -12,582,912
STAT  table scan rows gotten             15,499,845            0  -15,499,845
STAT  session pga memory                    196,608   19,857,408   19,660,800
STAT  logical read bytes from cache     299,958,272            0 -299,958,272

Mas, no final do dia, apenas a hora do relógio de parede importa. As etapas de carregamento e consulta são executadas muito mais rapidamente com tabelas temporárias.

A versão PL/SQL pode ser melhorada substituindo o BULK COLLECT com cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t . Mas ainda é significativamente mais lento do que a versão de tabela temporária.

Leituras otimizadas

A leitura da pequena tabela temporária usa apenas o cache do buffer, que está na memória. Execute apenas a parte da consulta várias vezes e observe como o consistent gets from cache (memória) aumentam enquanto o physical reads cache (disco) permanecer o mesmo.
select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache', 
'physical reads cache');

Gravações otimizadas

Idealmente, não haveria E/S física, especialmente porque a tabela temporária é ON COMMIT DELETE ROWS . E parece que a próxima versão do Oracle pode introduzir esse mecanismo. Mas não importa muito neste caso, a E/S do disco não parece desacelerar as coisas.

Execute a etapa de carregamento várias vezes e, em seguida, execute select * from v$active_session_history order by sample_time desc; . A maior parte do I/O é BACKGROUND , o que significa que nada está esperando por ele. Presumo que a lógica interna da tabela temporária seja apenas uma cópia dos mecanismos DML regulares. Em geral, novos dados de tabela podem precisa ser gravado em disco, se for confirmado. O Oracle pode começar a trabalhar nele, por exemplo, movendo dados do buffer de log para o disco, mas não há pressa até que haja um COMMIT real .

Para onde vai o tempo PL/SQL?

Eu não tenho idéia. Existem várias opções de contexto ou uma única conversão entre os mecanismos SQL e PL/SQL? Até onde sei, nenhuma das métricas disponíveis mostra o tempo gasto na alternância entre SQL e PL/SQL.

Talvez nunca saibamos exatamente por que o código PL/SQL é mais lento. Eu não me preocupo muito com isso. A resposta geral é que a grande maioria do trabalho de banco de dados precisa ser feito em SQL de qualquer maneira. Faria muito sentido se a Oracle gastasse mais tempo otimizando o núcleo de seu banco de dados, SQL, do que a linguagem complementar, PL/SQL.

Observações adicionais

Para testes de desempenho, pode ser útil remover o connect by lógica em uma etapa separada. Esse SQL é um ótimo truque para carregar dados, mas pode ser muito lento e consumir muitos recursos. É mais realista carregar uma tabela de amostra uma vez com esse truque e depois inserir dessa tabela.

Tentei usar o novo recurso Oracle 12c, desfazer temporário, e o novo recurso 18c, tabelas temporárias privadas. Nenhum deles melhorou o desempenho em relação às tabelas temporárias regulares.

Eu não apostaria nisso, mas posso ver uma maneira de os resultados mudarem completamente à medida que os dados aumentam. O buffer de log e o cache de buffer só podem ficar tão grandes. E, eventualmente, essa E/S em segundo plano pode aumentar e sobrecarregar alguns processos, transformando o BACKGROUND aguarde em um FOREGROUND esperar. Por outro lado, há tanta memória PGA para a solução PL/SQL, e então as coisas falham.

Finalmente, isso confirma parcialmente meu ceticismo em relação aos "bancos de dados na memória". O armazenamento em cache não é novidade, os bancos de dados fazem isso há décadas.