As 9 Regras Ninjas de Performance

Esse post resume muita coisa do que já passei.

Resolvi compilar uma série de regras para abordar os problemas mais comuns de performance. Essas são as “regras ninjas” para ajudar a guiar o trabalho do dia a dia e atingir bons resultados em pouco tempo.

 

REGRA 1: DISK - Monitore o consumo de recursos do banco de dados

O principal recurso do banco de dados é o disco, pois é lá onde os dados ficam armazenados. Quanto maior for a quantidade de dados a serem lidos, maior será o custo da consulta – portanto, ela será mais demorada. Quando for começar a analisar um banco de dados, esqueça temporariamente a questão de CPU e Memória. Eles são importantes, mas podemos deixar isso com a equipe de infra.

 

REGRA 2: INDEX - Crie índices para suportar consultas nas tabelas

Sugerir a criação de índice para melhorar a performance é meio óbvio. Todos sabem que tabelas sem índices é sinônimo de banco de dados lento. Então, por que as pessoas não criam índices?

O problema é que muitos desenvolvedores não se atentam a quais colunas (e a ordem) devem ser incluídas. As consultas buscam os índices para diminuir o consumo de recurso (disco). Acredito que o culpado seja nós mesmos, os DBA, que deveríamos fornecer uma melhor orientação aos desenvolvedores.

 

REGRA 3: CAST - Defina os tipos de dados adequados

O banco de dados relacional trabalha com dados tabulares e relacionamento entre tabelas. Isso permite aplicar uma série de validações de dados antes de inserir definitivamente dentro da base. Uma responsabilidade importante da modelagem de dados é definir os tipos de dados (BIT, INT, CHAR, VARCHAR) e sua condição de “nulabilidade” (NULL ou NOT NULL).

O fato é que frequentemente as aplicações desprezam essa etapa e definem a maioria dos campos como VARCHAR e NULL.

Quando a tabela emprega tipos de dados errados e a consulta realiza a conversão de dados, o processamento é feito linha a linha. Consequentemente, força-se a leitura completa da tabela, desprezando o uso de índices. No fim, o problema inicial de modelagem é postergado para um problema de lentidão no ambiente de produção.

 

REGRA 4: OR – Permita o compilador otimizar a consulta

Há casos em que as tabelas possuem os tipos de dado corretos e os índices necessários. Entretanto, a consulta foi construída de forma que dificulta o compilador SQL a otimizar o acesso ao dado, voltando ao comportamento de table scan.

O conceito de Searchable Arguments (SARG) é fundamental para compreender o funcionamento interno do compilador. Não adianta adicionar filtros e condições que não se enquadram no tipo SARG. Existem operadores (ex: NOT, OR) que podem impedir as possibilidades de otimização da consulta.

 

REGRA 5: JOIN - Utilize a junção de tabelas apropriadas

As informações estão distribuídas entre tabelas e para acessar um dado é necessário junta-las. Quanto menor for a quantidade de registros retornado de cada tabela, melhor será o desempenho final.

Aquilo que parece ser fácil pode se tornar bem complexo. A operação de JOIN é conhecida matematicamente como a relação de produto cartesiano, ou seja, todos os elementos de um conjunto são ligados aos elementos do outro conjunto.

Quando a operação de JOIN é definida incorretamente, o número de registros ligados rapidamente se multiplica. É nesses casos que observamos os operadores mais custosos ocorrendo.

 

REGRA 6: TRAN - Entenda as unidades de transações

Um banco de dados transacional gasta mais recursos do que um não-transacional. As transações permitem que as informações sempre estejam em um estado consistente, mesmo que o dado esteja distribuído em diferentes tabelas.

Não existe uma fórmula para seguir e é difícil balancear entre uma transação curta x longa:

  • Transações curtas adicionam breves latências ao final da transação
  • Transações longas consomem recurso enquanto estiver em andamento

Em ambientes desbalanceados, o efeito mais comum é a ocorrência de bloqueios e deadlocks ao longo do dia.

 

REGRA 7: NOLOCK - Evite os bloqueios desnecessários

Normalmente essa regra se resumiria a usar NOLOCK.

NOLOCK é uma hint bastante usada no SQL Server 2000 e tem sido colocada em prática até os dias de hoje. A partir do SQL Server 2005, existem alternativas mais eficazes para resolver problemas de bloqueio: read committed snapshot e snapshot transaction.

Nesse caso, é importante determinar a verdadeira causa dos bloqueios ao invés de contorna-los com NOLOCK.

 

REGRA 8: PROC - Codifique as consultas com Stored Procedures

Existe uma legião de desenvolvedores que prefere descartar o uso de stored procedures e usar comandos ad-hoc de SELECT, INSERT, UPDATE, DELETE diretamente contra a base. As vantagens de uma procedure são claras em pelo menos dois cenários:

  • Evitar SQL injection
  • Capturar estatísticas de execução

O uso de stored procedures permite encapsular a camada de dados e esconde parte da modelagem física de dados. Isso facilita a monitoração e correção de problema.

 

REGRA 9: TEMP - Estude os processamentos Batches

A maioria das regras anteriores se aplicam para cargas de natureza OLTP. Entretanto, existe uma carga de processamento Batch que pode mudar a forma de analisar a performance.

Normalmente tabelas temporarias são usadas para processar grande numero de registros, favorecendo os operadores custosos de Hash e Sort. Nesse caso é importante manter as estatísticas corretas, recompilar ou forçar planos de execução.