28 de fev de 2013


Olá!
Vou começar a postar hoje a primeira parte meu trabalho que desenvolvi para meu curso de especialização.
Hoje vou falar SOBRE:

Execução de comandos DML.

Para um entendimento melhor sobre os comandos por parte dos usuários, esta seção visa exibir como as instruções são tratadas pelo banco de dados Oracle desde seu envio até sua execução e retorno. A execução de comandos de manipulação de dados segue um fluxo condicional e para entendê-lo em cada um dos comandos DML, é necessário o conhecimento de alguns conceitos que serão descritos mais adiante.

O fluxo de execução de uma instrução SELECT, segundo José Lorenzo, se dá conforme Figura 1 e processo descrito abaixo.
  1. Um programa cliente (user process) submete uma instrução SELECT para um dispatcher process que envia o comando para um shared server process (processo de servidor compartilhado) disponível;

Figura 1 - Processando uma instrução SELECT. (Fonte: Oracle Corporation)

  1. O server process realiza uma busca na library cache a procura de uma instrução SELECT compatível a com que foi solicitada (esse teste de compatibilidade varia de acordo com a configuração do parâmetro de banco: CURSOR_SHARING). Se não encontrar, o banco irá compilar a nova instrução e armazená-la na shared pool (library cache). A compilação da instrução SELECT consome CPU, enquanto que o armazenamento na shared pool utiliza um latch disponível. Nesse mesmo momento, são verificadas questões como: quais objetos serão acessados (tabelas, visões, sinônimos,etc.), quais são as colunas ou campos que compõem os objetos, se o usuário possui permissão de acesso ao objeto, etc. Caso encontre a instrução na library cache, o server process não realiza algumas das funções do parsing pois em outro momento já tinham sido realizadas;
  2. O server process procura na buffer cache os blocos de dados que necessita para atender à requisição. Caso encontre os dados necessários estes, são enviados ao user process e esses dados são movidos para o final da fila LRU indicando que o bloco de dados foi utilizado recentemente. Caso os dados necessários não sejam encontrados nos blocos da buffer cache, o server process irá buscar os dados nos datafiles. Isto requer uma ou mais operações de I/O. Uma vez encontrados os dados, os blocos que os contêm são copiados para a buffer cache por meio de latch.
O fluxo de execução de uma instrução INSERT se dá conforme descrito abaixo.
  1. Um programa cliente (user process) submete uma instrução INSERT para um dispatcher process que envia o comando para um shared server process disponível, semelhante ao ocorrido no SELECT;
  2. O server process realiza uma busca na library cache a procura de uma instrução INSERT compatível com a que foi solicitada. Se não encontrar, o banco irá compilar a nova instrução e armazená-la na shared pool (library cache). Caso encontre a instrução na library cache, o server process não realiza algumas das funções do parsing pois em outro momento já foram realizadas.
  3. O server process realiza a escrita do vetor de alteração (mínimo de informação necessária para reconstruir ou refazer todo o trabalho) no redo log no buffer de log antes de inserir o dado em um bloco de dados (buffer cache). Após a escrita do vetor de alteração, os dados da instrução são escritos na buffer cache que terá o bloco de dados envolvido nessa alteração indicado como sujo (flag que indica que esse bloco deve sofreu alteração e deve ser efetivado em disco);
  4. O processo de background LGWR executa a escrita do conteúdo do buffer de log (memória) no redo log file (disco) quando uma instrução COMMIT é efetuada. Mesmo com a realização de um COMMIT, os dados não serão escritos no disco (datafiles). O processo de background DBW é quem realiza essa tarefa.
O fluxo de execução de uma instrução UPDATE se dá conforme descrito abaixo.
  1. Um programa cliente (user process) submete uma instrução UPDATE para um dispatcher process que envia o comando para um shared server process disponível;
  2. Um processo de busca do dado a ser alterado ocorre semelhante ao processo descrito para a instrução SELECT
  3. O server process escreve o vetor de alteração no redo log no buffer de log antes de alterar o dado no bloco de dados na buffer cache. Após a escrita do vetor de alteração, os dados da instrução são alterados na buffer cache que terá o bloco de dados envolvido nessa alteração indicado como sujo;
  4. Assim como no processo de uma instrução INSERT, o LGWR escreve o conteúdo do buffer de log no redo log file quando uma instrução COMMIT é efetuada e o DBW escreve o conteúdo do buffer cache no disco seguindo sua regra de execução.
O fluxo de execução de uma instrução DELETE é muito parecida com a de uma instrução UPDATE, sendo que os dados não são excluídos de fato da memória e nem do disco, e sim terão sua área de armazenamento indicada como disponível para uso.

Conforme informado, fazem-se necessárias algumas definições de termos e recursos envolvidos no processo de instrução DML:
  • Dispatcher Process (processo despachante): é um processo de background (segundo plano) que está condicionado à configuração do Oracle Multi-thread Server. Ao menos um dispatcher process é criado para cada protocolo de comunicação em uso (D000, D0001, ..., Dnnn). Cada dispatcher é responsável pelo direcionamento das requisições dos processos dos usuários conectados ao BD para o shared server process disponível (Snnn) e pelo retorno da resposta de volta para o user process apropriado (FILHO);
  • User Process (processo de usuário): é um processo de background que executa o código do usuário e faz as requisições ao BD. Esse processo se comunica com um server process de forma direta: com um server process dedicado ao user process; ou indireta: por meio de um dispatcher (LORENZO);
  • Server Process (processo de servidor): é um processo de background responsável por atender às requisições de um user process (quando dedicado) ou de vários user processes (quando compartilhado). É iniciado quando um user process abre um canal de comunicação e termina quando a ligação é concluída. Interpreta as requisições e as executa, gerindo o envio dos resultados para o cliente (LORENZO);
  • Datafiles: são ficheiros armazenados no disco do servidor, onde o Oracle armazena os dados e as estruturas de controle da base de dados (WATSON, 2009);
  • SGA (System Global Area ou Área Global do Sistema): é uma área de memória do servidor utilizada para armazenar dados compartilhados pelos usuários da base de dados. Armazena dados, informação de controle e instruções SQL (WATSON, 2009);
  • Shared Pool (memória compartilhada): é uma estrutura da SGA utilizada para armazenar o dicionário de dados, comandos executados recentemente de SQL e PL/SQL, cache de resultado da função, buffer de mensagens de execução paralela e estruturas de controle (WATSON, 2009);
  • Library Cache (cache de biblioteca): é uma subestrutura da shared pool usada para armazenar o código executado recentemente, na sua forma analisada por parse. A análise por parse é a conversão do código escrito pelos programadores em algo executável e é um processo que o BD Oracle faz por demanda. Armazenar em cache o código analisado por parse na shared pool, para que ele possa ser reutilizado sem a necessidade de ser reanalisado melhora muito o desempenho (WATSON, 2009);
  • Latch: é um mecanismo de alocação de espaço na SGA serializado e desenhado para que sejam alocados por curtos períodos de tempo. Ele controla e protege os processos que desejam acessar áreas compartilhadas da SGA, permitindo que somente um processo de cada vez acesse a estrutura requisitada, evitando corrupção da memória, ou seja, mantendo a integridade (SILVA, 2012);
  • Buffer Cache: é uma área de trabalho do BD para execução de instruções SQL. Ao atualizar os dados, as sessões dos usuários não atualizam diretamente no disco. Os blocos de dados que contêm os dados de interesse são primeiramente copiados no buffer cache do banco. Consultas, inserções de novas linhas e exclusão ou alterações de linhas, são aplicadas a essas cópias dos blocos de dados no buffer cache. Os blocos permanecerão no cache por algum tempo, até que o buffer que eles estão ocupando seja requisitado para armazenar outro bloco em cache (WATSON, 2009);
  • Buffer Log: é uma área de preparação pequena e de curto prazo para os vetores de alteração antes que eles sejam gravados no redo log do disco. Um vetor de alteração é uma modificação aplicada a algo, por exemplo a execução de instruções DML gera vetores de alteração aplicadas aos dados. O redo log é a garantia do banco de que os dados nunca serão perdidos. As informações de redo não são gravadas nos arquivos de redo log pelos processos de servidor de sessão, se fossem, as sessões teriam que aguardar as operações de I/O de disco serem completadas sempre que elas executassem uma instrução DML. Em vez disso, as sessões gravam o redo no buffer de log na memória que é muito mais rápido do que gravar no disco. O buffer de log (que pode conter vetores de alterações de muitas sessões) é então gravado nos redo log files. Uma gravação do buffer de log no disco pode ser um lote de muitos vetores de alteração provenientes de várias transações, mesmo assim, são gravados no disco praticamente em tempo real – e quando uma sessão emite uma instrução COMMIT, a gravação do buffer realmente acontece em tempo real. As gravações são realizadas pelo processo de background Log Writer. À medida que os vetores de alteração são gravados, o espaço ocupados por ele torna-se disponível e pode ser sobrescrito por mais vetores (WATSON, 2009);
  • Redo Log File: esse arquivo armazena uma cadeia contínua em ordem cronológica de cada vetor de alteração aplicado ao banco. Os vetores de alteração contém informações mínimas e são usados para refazer ou desfazer uma manipulação do dado. À medida que as sessões de usuários atualizam os dados no buffer cache do banco, elas também gravam vetores de alteração mínimos no buffer de redo log. O LGWR continuamente grava os dados desse buffer para o redo log file para garantir a informação (WATSON, 2009);
  • Control File (arquivo de controle): esses arquivos armazenam a estrutura do banco de dados Oracle e seu sincronismo (através do SCN). O control file é pequeno, mas é vital. Sem a sua presença não é possível inicializar o banco (WATSON, 2009);
  • Log Writer (LGWR): é um processo de background responsável por gravar o conteúdo do buffer log nos redo log files no disco. Esse processo é um dos principais gargalos na arquitetura Oracle. É impossível executar comandos DML mais rápidos do que o LGWR pode gravar os vetores de alteração no disco. Existem três circunstâncias que obrigarão o LGWR a fazer flush (descarga) para o buffer log: se uma sessão emitir um COMMIT, se o buffer log estiver um terço completo e se o DBW for gravar buffers sujos no disco (WATSON, 2009);
  • Database Writer (DBWn): é um processo de background responsável por escrever no disco o conteúdo dos buffers (do buffer cache). Uma instância pode ter vários database writers (20 no máximo). Geralmente é utilizado um DBW para cada oito CPUs. O DBW grava buffers sujos do buffer cache do banco nos datafiles (não à medida que se tornam sujos). Ele grava o menor número de buffers possível, o suficiente para resolver o problema, isso para evitar o I/O de disco pois esse processo prejudica o desempenho do banco. O database writer utiliza o LRU, escrevendo no disco os buffers com blocos de dados menos usados recentemente, isso porque um bloco que foi usado recentemente tem uma possibilidade razoável de ser usado novamente. Existem quatro circunstâncias em que o DBW grava os dados dos buffers no disco: quando à ausência de buffers livres, excesso de buffers sujos, um tempo limite de três segundos e quando há um checkpoint (WATSON, 2009);
  • Checkpoint Process (CKPT): é um processo de background responsável por sinalizar o DBWn com checkpoints, além de atualizar as informações de checkpoint nos cabeçalhos dos datafiles e nos control files (WATSON, 2009);
  • LRU (Least Recently Used - Menos Recentemente Usada): é uma lista que contém blocos de dados que foram solicitados por um user process. Como essa lista possui um dimensionamento limitado, quando ela está completamente cheia e um novo bloco de dados tem a necessidade de ser alocado nela para atender a uma demanda, algum bloco deve ser retirado da lista. Esse bloco de dados é o primeiro da lista, pois se ele ocupa essa posição, significa que foi o menos recentemente utilizado (FILHO, 2012).

Watson, John (2009). OCA Oracle Database 11g - Administração I (Guia do Exame 1Z0-052). 1ª edição. Editora Bookman.

Silva, Paulo Henrique (s.d.) (2012). Tuning de bancos de dados Oracle. SQL Magazine 95 .

Lorenzo, José A. Disponível em: http://aserlorenzo.com/manSQL/Oracle/introducao/oracleArquitectura.htm.  Acessado: 29/11/2012.


Oracle Corporation. Oracle9i Database Concepts Release 2 (9.2). Disponível em:  http://docs.oracle.com/cd/B10500_01/server.920/a96524/c09procs.htm. Acessado: 29/11/2012.


Filho, Gesualdo Saudino. A arquitetura ORACLE. Publicadao em Linha de Código. Disponível em: http://www.linhadecodigo.com.br/artigo/99/a-arquitetura-do-oracle.aspx. Acessado: 29/11/2012.

------------------------------------------------------------------------------------------------------------------------
Espero poder ajudar com esse post, no entendimento do funcionamento de comandos DML.

Até a próxima, onde pretendo falar sobre Parsing.

Raphael Fernandes, quinta-feira, fevereiro 28, 2013

Sem comentários

27 de fev de 2013

Pessoal,

Estou desenvolvendo, em parceria com um colega (Thiago Marçal), um projeto para apresentar como TCC na pós de banco  de dados que estou concluindo. O título do trabalho é: Tuning em banco de dados Oracle: aumentando O DESEMPENHO reduzindo o hard parse.
O trabalho está em fase de revisão final, e assim que der vou postando partes que julgo importantes para o entendimento do assunto. Ficou um material bem interessante, pois pesquisei e experimentei bastante sobre o que escrevi.

Por enquanto é isso. Espero fazer a postagem da primeira parte o quanto antes.

Grande abraço a todos, obrigado pela atenção e tenha um bom dia!

Raphael Fernandes, quarta-feira, fevereiro 27, 2013

Sem comentários

Olá.

Vou compartilhar com vocês um problema que ainda não consegui resolver e gostaria de, caso algum leitor saiba sobre o assunto e quiser compartilhar comentando, que me ajude por favor.

É mais ou menos o seguinte...

Na empresa onde sou DBA, utilizamos o banco Oracle 10G (release 10.2.0.3) e recentemente realizei uma alteração (para efeito de teste) do parâmetro CURSOR_SHARING. Alterei ele do seu valor default "EXACT" para o valor "SIMILAR".
Com a alteração, a taxa de hard parse diminuiu, e obtive um alto índice de reuso de query (ou scripts de modo geral).
Os testes estavam indo bem, quando és que surge uma consulta semelhante a seguinte:

select 'teste' as campo, 'Y' as tipo from dual
union
select 'teste1', 'N' from dual;

Com o parâmetro alterado, essa consulta foi interpretada como:

select '"SYS_B_0"' as campo, '"SYS_B_1"' as tipo from dual
union
select '"SYS_B_2"' as campo, '"SYS_B_3"' as tipo from dual;

Até então, tudo ocorreu conforme esperado, porém na aplicação que faz uso dessa base existia um teste conforme o indicado abaixo:

<%
'Código ASP
...
if cstr(rs.fields("tipo")) = "Y" then
<< fazer algo xcvdxwwx >>
else
<< fazer algo yzwyzee >>
end if
...
%>

Mesmo quando o retorno da consulta era = "Y", nunca entrava no if (e eu testei a consulta e ela realmente retornava Y).
Quando fui verificar o retorno pela aplicação, o campo "tipo" retornava "Y ¢¥¥├ò", ou seja, com um lixo após o valor.
Rodei a mesma consulta pelo sqlplus, e realmente o valor do retorno era apenas "Y".

Tentei alterar o provider da string de conexão do banco para ver se era esse o problema, mas o mesmo persistiu. O Oracle Client no servidor da aplicação é o 10G.

Não consegui entender o erro, e em todas as documentações e livros que pesquisei, os problemas oriundos da alteração desse parâmetro acarreta apenas em queda de performance (devido a por exemplo reutilizar um plano NÃO otimizado para uma consulta).

Esse problema inviabilizou a alteração que se comportara muito bem em outros aspectos.

Entendo que quando pensamos em reuso através de bind variables, associamos apenas à alterações dos parâmetros na seleção dos dados e não na projeção como é o caso citado.

Alguém tem alguma ideia sobre o que pode ser e se tem alguma alteração que possa ser feita para conseguir o ganho da performance dos "soft parses"?

Conto com o conhecimento de vocês!

Grato!!

Raphael Fernandes, quarta-feira, fevereiro 27, 2013

6 comentários

Olá, meus caros!

Criei esse blog para divulgar  alguns problemas, soluções e comentários sobre diversas situações vivenciadas no dia-a-dia do trabalho da área de Tecnologia de Informação, principalmente relacionadas ao minha área de atuação: Banco de Dados.

Raphael Fernandes, quarta-feira, fevereiro 27, 2013

Sem comentários