Social Icons

26 de set. de 2011

Gerenciando o armazenamento/desempenho de colunas LOB


Olá pessoal,
    
     No artigo de hoje irei comentar sobre um assunto que foi parte do meu trabalho na semana passada: o gerenciamento do armazenamento e desempenho das colunas LOB (Large Object), mais especificamente, os tipos de dados CLOB (Character LOB) e BLOB (Binary LOB). Para melhor entendimento deste artigo, é necessário ter conhecimento prévio dos tipos de dados LOB (CLOB, BLOB etc.).
   
     Para os DBAs que já administram ou que passarão a administrar tabelas com tipos de dados LOB, ressalto que por questões de performance e manutenção, vale a pena separar o armazenamento das colunas LOB em um tablespace próprio, ou seja, em um tablespace separado da tabela. Quando colunas do tipo CLOB ou BLOB são armazenadas no mesmo tablespace da tabela e quando essas colunas armazenam mais que 4000 bytes ou 4000 caracteres em cada linha da tabela,  elas causam fragmentação dos datafiles e consequentemente sérios problemas de performance.
    
     Para demonstrar um pouco destes conceitos, vamos criar uma tabela chamada CLIENTE, que contém uma coluna do tipo BLOB para armazenar as fotos de cada cliente. Segue abaixo o código DDL para criar a tabela, a coluna BLOB e o índice da coluna BLOB (criado automaticamente em colunas do tipo CLOB e BLOB) em tablespaces separados:
          
         CREATE TABLE CLIENTE (  id    NUMBER,
                             nome  VARCHAR2(50),
                             foto  BLOB)
            LOB (FOTO) STORE AS lb_foto (TABLESPACE users_l
                                         INDEX ix_foto (TABLESPACE users_i))
      TABLESPACE users_d;
 
     Observações:
                - A tabela será armazenada no tablespace USERS_D;                 
                - A coluna foto do tipo BLOB será armazenada no tablespace USERS_L;
                - O índice da coluna foto será armazenado no tablespace USERS_I. O índice, assim como a coluna BLOB, também está sendo armazenado em um tablespace separado para facilitar o gerenciamento.

     Agora iremos ver a parte mais intrigante deste artigo. Supondo que a tabela CLIENTE possui 1000 linhas e que cada linha tem um tamanho de 1 MB, a tabela terá um tamanho total de 1000 MB . Em cada linha, a coluna foto tem um armazenamento médio de 980 kbytes. Se executarmos uma instrução para apagar as 100 primeiras linhas (Ex.: DELETE FROM CLIENTE WHERE ROWNUM <101), com que tamanho físico irá ficar a tabela?
         1- 1000 MB;
         2- 995,70 MB.
         3- 900 MB;

     A resposta correta é a opção 1. Fisicamente falando, a tabela continuará ocupando blocos nos tablespaces de dados e índices até que eles sejam reutilizados (sobrescritos). Um dos procedimentos para liberar o espaço físico das tabelas é a sua compactação através do conhecido SHRINK e depois um resize no(s) datafile(s) referentes ao seu(s) tablespace(s) Se executarmos em seguida um SHRINK na tabela, fisicamente ela inda ocupará o espaço da opção 2, pois o SHRINK só libera o espaço das colunas não lob. Para liberar todo o espaço ocupado pelas linhas que foram deletadas, é necessário compactar também cada coluna LOB que a tabela possui. Neste caso, somente após executar o SHRINK na tabela e na coluna LOB é que a gente vai chegar ao tamanho de 900 MB, da opção 3.

     Para liberar o espaço não utilizado pelas linhas apagadas na coluna LOB, temos que compactar a coluna foto, executando o comando abaixo:
           ALTER TABLE CLIENTE MODIFY LOB (FOTO) (SHRINK SPACE);

     É importante ressaltar que, por padrão, dados do tipo LOB serão armazenados no mesmo segmento da tabela se eles tiverem até 4000 bytes ou 4000 caracteres (dependendo da configuração do BD). Se você quiser, você pode alterar a definição da coluna para que ela sempre tenha o seu próprio segmento, executando o comando abaixo:
           ALTER TABLE CLIENTE MODIFY LOB (FOTO) STORE AS (DISABLE STORAGE IN ROW);

     Outra dica para quem quer melhorar o desempenho no acesso às colunas do tipo LOB, é habilitar o cache, que por padrão é desabilitado em LOB. A exceção só ocorre se os dados tiverem menos que 4000 bytes ou 4000 caracteres, pois nestes casos eles são armazenados no mesmo segmento da tabela, usando também a definição de CACHE. Quando uma instrução SQL referencia uma linha de uma coluna do tipo LOB (maior que 4000 bytes ou caracteres), o BD acessa os dados diretamente do(s) datafile(s) e devolve o resultado para o cliente. Na configuração padrão, os dados não vão para a Buffer Cache, portanto, toda vez que você acessar uma coluna do tipo LOB, você estará fazendo I/O físico. Para otimizar o seu desempenho, na definição da coluna, especifique que ela seja armazenada em cache. Deste modo, o I/O físico minimiza, sendo substituído por I/O lógico, que é muito mais rápido! Tome apenas 1 cuidado. Colunas do tipo LOB possuem muitos dados. Certifique-se antes de que a Buffer Cache do BD terá espaço suficiente para comportar os dados da coluna. Segue abaixo um exemplo para modificar a definição de uma coluna do tipo LOB:

ALTER TABLE tabela MODIFY LOB(coluna) (CACHE);



CONCLUSÃO

    Tabelas com colunas LOB requerem cuidados especiais! Para facilitar o gerenciamento, melhorar performance e evitar fragmentação de linhas, armazene as colunas LOB em um tablespace separado. Se você tem tabelas com colunas LOB que sofrem muitas deleções, é necessário criar rotinas de manutenção periódicas para compactar as colunas LOB e liberar espaço de armazenamento não utilizado pelas linhas que foram deletadas.

     Em um dos BDs de produção que eu administro, temos um sistema que possui uma tabela temporária que tem uma coluna do tipo BLOB. Por ser uma tabela temporária,  ocorrem constatemente muitas inserções e deleções nesta tabela. A tabela é de um sistema desenvolvido por terceiros. Na semana passada verifiquei que este sistema havia crescido muito mais do que o esperado nos últimos meses. Descobri que a causa do crescimento da da tabela temporária foi porque ela estava sendo muito utilizada e porque não estava sendo liberado o espaço da coluna BLOB das linhas deletadas. Todos os dados do sistema (sem índices) estavam ocupando 33 GB de espaço de armazenamento em seu respectivo tablespace. Após compactar a coluna BLOB, foram liberados aproximadamente 18 GB. Depois de compactar a tabela, para liberar espaço físico em disco, tive que redimensionar o(s) datafile(s) do tablespace LOB.

      A dica da compactação em LOBs é muito útil, pois pode ajudar a melhorar o desempenho de sistemas, liberar espaço em disco e até mesmo diminuir o tempo dos backups.


Por hoje é só!

[]s

17 de set. de 2011

Otimizando a performance de aplicações com o uso de stored procedures


Olá pessoal,
    
     No artigo de hoje vou comentar sobre o ganho de performance com o uso de stored procedures (SPs), nas aplicações que acessam e/ou atualizam dados em Sistema Gerenciadores de Bancos de Dados Relacionais. As stored procedures, bem como, as functions, packages e triggers, foram implementadas na versão 7 do Oracle Database (1992) e seu uso (em substituição ao uso de instruções SQL submetidas individualmente) pode otimizar drásticamente a performance das aplicações que utilizam SGBDs relacionais, principais aquelas que executam grandes transações.
    
     Apresentarei neste artigo, uma aplicação bem simples que chama uma stored procedure (SP), que   por sua vez, realiza uma transação de transferência bancária entre 2 contas correntes e que contém uma regra de negócio, também simples, para verificar se existe saldo na conta de origem. Sei que muitos profissionais de TI são contra codificar regras de negócios dentro de SPs, pois aprendemos em Engenharia de Software moderna, que as regras de negócio devem ficar na aplicação, em um componente separado, que por sua vez, deve ser armazenado em um servidor de aplicação (e nunca no BD), mas tenho certeza de que você vai gostar do resultado do final deste artigo, se sua prioridade for performance!

     Já desenvolvi várias aplicações com regras de negócio tanto no servidor de aplicação quanto em stored procedures, por isso, posso afirmar que sempre consegui melhor performance naquelas aplicações que chamavam stored procedures. Porém, é importante avaliar e testar cada caso. Para quem nunca codificou regras de negócio em stored procedures, isso pode parecer estranho ou errado, mas a vantagem do ganho de performance, justifica (e muito) a prática. Grandes transações que envolvem manipulação condicional de dados podem ficar mais rápidas com SPs. Entre diversos benefícios de segurança e performance que as stored procedures proporcionam, o principal e que eu acho mais fácil de explicar, é que elas reduzem o tráfego de dados pela rede e o tempo de espera destes dados pela aplicação.

     É muito simples o raciocínio: se uma transação realiza 10 operações no Banco de Dados, o que é mais rápido: sair do servidor de aplicação e ir ao BD 10X (trafegando 10X pela rede), ou ir uma 1X só, executar as 10 operações e retornar o resultado para o servidor de aplicação? Quando você tem que comprar 10 produtos no mercadinho da esquina, o que é mais rápido? Ir 10X trazendo cada vez 1 único produto ou levar uma sacola e trazer os 10 produtos de uma só vez?

     Em aplicações críticas, que exigem alta performance, o que é mais importante: seguir a regra de criar aplicações N camadas (com regras de negócios SEMPRE em um servidor de aplicação) ou usar recursos alternativos (neste caso, as stored procedures) para desenvolver uma aplicação mais rápida
    
    Vou demonstrar a seguir, um exemplo de uma aplicação que eu desenvolvi com o Dot Net Framework 3.5, para provar o conceito de que SPs podem otimizar a performance das aplicações. A aplicação, chamada Teste de performance de transações (ver Figura 1), poderá ser baixada para testes e é totalmente parametrizável (ver arquivo TesteTransacao.exe.config). Ela simula a realização de simples transferências entre contas bancárias, retirando o valor de uma conta corrente (conta origem) e depositando o respectivo valor em outra conta corrente (conta destino).
  

Figura 1 - Tela principal da aplicação "Testes de performance de Transações"
    
     A operação de transferência ocorre em modo transacional (deve fazer tudo ou nada, se 1 passo falhar, desfaz os passos anteriores) e é composta por 3 passos sequenciais:
          1) Verificar se a conta origem possui saldo para efetuar a transferência;
          2) Retirar (sacar) valor da conta origem;
          3) Depositar valor na conta destino;
        
             Obs.: Os passos 2 e 3 são executados somente se a conta origem possuir saldo (verificado no passo 1).

     A aplicação está disponível para download no MEU ONE DRIVE (ver final do painel direito das páginas do meu blog), pasta Oracle -> Scripts, arquivo TesteTransacao.zip. Para efetuar a instalação e utilizá-la, siga os passos abaixo:

        1- Descompacte o arquivo TesteTransacao.zip informando uma senha que deverá ser obtida assinando a newsletter que encontra-se no painel direito deste blog.

        2- Conecte-se no BD desejado e instale os objetos de BD (tabela CONTA e package PKG_CONTA) que estão no arquivo Script_BD_Teste_Transacao.sql. Instale os objetos no schema de um usuário que será utilizado pela aplicação para conectar-se no BD.

        3- Configure os valores (values) dos parâmetros (keys) do arquivo TesteTransacao.exe.config, conforme indicações abaixo:
             a) instance_name = Nome da instância do BD onde os objetos foram criados. Especificar nome de uma instância cadastrada no arquivo tnsnames.ora da máquina em que a aplicação irá ser executada;
             b) user_name = Nome do usuário que a aplicação utilizará para conectar-se no BD;
             c) pwd_user = Senha do usuário que a aplicação utilizará para conectar-se no BD;
             d) idContaOrigem = Número da conta origem;
             e) idContaDestino = Número da conta destino;
             f) vlInicialContaOrigem = Valor inicial da conta origem;
             g) vlInicialContaDestino = Valor inicial da conta destino;
             h) intTotalInteracoes = Valor indicando qtde. de operações de transferências que serão realizadas;
             i) vlTransferencia = Valor da transferência.

     Observações: São pré-requisitos para executar esta aplicação, ter o Dot Net Framework 3.5 instalado (SOs Windows mais recentes já possuem) e o Oracle Data Provider for .Net.
  
    Para efetuar os testes de performance, basta clicar nos 2 botões existentes na tela principal da aplicação: Transferência SQL e Transferência com SP. O botão Transferência SQL submete instruções SQL para o BD, enquanto que, o botão Transferência com SP, executa uma stored procedure no BD (executando dentro de uma procedure os 3 passos em uma única chamada ao BD).
 
     Vejam abaixo, a performance de testes que eu fiz:
  
TESTE executando 1000 transferências bancárias

    a) Tempo de Transferência do botão Transferência SQL (ver Figura 2): 3,8s

Figura 2 - Teste de 1000 transferências com SQL (ad hoc)
     b) Tempo de Transferência do botão Transferência com SP (ver Figura 3)1,7s

Figura 3 - Teste de 1000 transferências com SP



Observações:
    Também disponibilizei o código-fonte da aplicação deste artigo (arquivo Fontes_TesteTransacao.zip), na mesma pasta que disponibilizei a aplicação. A senha para descompactação deste arquivo é a mesma do arquivo da aplicação.

CONCLUSÃO:

     Nos testes realizando 1000 transações conseguimos verificar que a performance delas utilizando SP foi bem superior, apresentando um desempenho 220% mais rápido. A transação bancária deste artigo é bem simples e possui apenas 3 operações. É importante ressaltar que em transações maiores, o ganho de desempenho também será maior!

     Mais detalhes, sobre a estrutura da aplicação, o porquê da stored procedure apresentar um desempenho superior neste exemplo e sobre a implementação de regras de negócio na aplicação ou na stored procedure, eu deixo para explicar nos seguintes treinamentos:
          - SQL Tuning (presencial);
          - PL/SQL Essentials and Tuning (presencial);
          - PL/SQL Tuning (videoaulas).

  Para aqueles que quiserem verificar a opinião de mais profissionais sobre o desempenho das stored procedures e a questão polêmica das regras de negócios dentro delas, sugiro a leitura da discussão Regras de Negócio em Stored Procedures ou Desenvolvimento em Camadas, no Linkedin, Grupo NET Framework - Brasil.


Bom pessoal, por hoje é só!
Espero que tenham gostado. Qualquer dúvida, é só deixar um comentário.

[]s

 

LINKS ÚTEIS

Total de visualizações de página

Seguidores

Meu One Drive (antigo Sky Drive)