segunda-feira, 10 de agosto de 2009

20 dicas para criar melhores procedures

Dicas para escrever melhores procedure em T-SQL

1. Colocar as palavras chaves em UPPERCASE, para melhorar a legibilidade do código, e procure identar de maneira correta o seu código. Afinal, isso

SELECT
a.nome,
a.email,
p.vlrcusto
FROM
antecessores a
JOIN predecessores p ON (p.codigo=cod_predecessores)

é melhor que isso

select a.nome, a.email, p.vlrcusto
from antecessores a
join predecessores p on (p.codigo=cod_predecessores)

2. Procure usar sempre sintaxe no padrão ANSI 92 sempre que possível. O padrão antigo ainda é suportado mas há uma grande chance de ser deprecated em versões futuras do MS-SQL SERVER. Use:

SELECT
a.nome,
a.email,
p.vlrcusto
FROM
antecessores a
JOIN predecessores p ON (p.codigo=cod_predecessores)

Ao invés de

SELECT
a.nome,
a.email,
p.vlrcusto
FROM
antecessores a, predecessores p
where p.codigo=cod_predecessores

3. Use o menor número de variáveis possível, para liberar espaço no cachê do SQL Server.
4. Tente minimizar o uso de Queries Dinâmicas, pois o seu uso requer que o servidor recompile a query a cada execução para montar um novo execution plan. Por exemplo, a seguinte query, pode realizar uma execução com o código igual a 100 e depois uma outra com o código igual a 101, e não haverá recompile no servidor para cada execução, pois o mesmo execuction plan será usado nas duas situações:

SELECT
a.nome
FROM
Antecessor a
WHERE
a.codigo=@codigo

Porém, o seguinte código

SELECT
a.nome
FROM
Antecessor a
WHERE
a.codigo=’ ‘ +@codigo

Obrigará o servidor a realizar a recompilação da query, a cada execução, portanto a query se torna mais lenta.

5. Use nomes “completos”, especificando o nome do Database, schema e nome da procedure, e especifique também o nome do schema na criação da procedure. Esse é um pequeno detalhe que pode levar a uma consulta ao cachê da procedure para verificar o seu execution plan.

6. Utilize o comando SET NOCOUNT ON antes dos comandos dentro da sua procedure. Esta configuração, faz com que o servidor mostre o número de registros afetados pelos scripts. Isso pode causar um tráfego de rede extra afetando a performance principalmente se a procedure é chamada com freqüência.

7. Não utilize o prefixo “SP_” pois o prefixo é reservado para procedures do sistema. Qualquer procedure que tem este prefixo, causará um lookup no banco MASTER pois o servidor verifica se existe uma procedure com o nome especificado no banco MASTER, e se existir, a sua procedure nunca será executada.

8. O sp_executeSQL and the KEEPFIXED PLAN evitam a recompilação da query. Se você precisa executar uma query dinâmica parametrizada, use o SP_executesql ao invés de EXEC para evitar a recompilação da procedure.

sp_executesql N'SELECT * FROM mydb.dbo.emp where empid = @eid', N'@eid int', @eid=40

é melhor que

EXEC(‘SELECT * FROM mydb.dbo.emp where empid =’+@ID)

Quando estiver buscando dados de tabelas temporárias, use a OPTION KEEPFIXEDPLAN, para não realizar a recompilação.

9. Para atribuições em variáveis, utilize sempre o SELECT e não o SET. Simplesmente é mais rápido e permite a atribuições em múltiplas variáveis.

SELECT @Var1 = @Var1 + 1, @Var2 = @Var2 – 1

Ao invest de:

SET @Var1 = @Var1 + 1

10. Cuidado ao usar os operadores na cláusula WHERE. Os operadores que envolvem igualdade sempre serão mais rápidos. Em linhas gerais, isso

SELECT nome FROM mailing WHERE codigo <= 4

Pode ser melhor que isso

SELECT nome FROM mailing WHERE codigo <>

11. Elimine o número de comparações desnecessárias. Por exemplo, por que fazer

SELECT emp_name FROM table_name WHERE emp_name = 'EDU' OR emp_name = 'edu'

Se podemos fazer:

SELECT emp_name FROM table_name WHERE LOWER (emp_name) = 'edu'

Procure não usar o operador in com subqueries, trocando estas comparações por EXISTS

SELECT * FROM employee WHERE NOT EXISTS (SELECT emp_no FROM emp_detail)

Ao invés de

SELECT * FROM employee WHERE emp_no NOT IN (SELECT emp_no from emp_detail)

12. CAST e CONVERT. O Cast é um comando padrão ANSI e o CONVERT funciona apenas no MS-SQL. Também é possível que o CONVERT seja deprecated em versões futuras. Utilize o CONVERT apenas quando precisar formatar datas.

13. Cuidado ao usar o DISTINCT e o ORDER BY, usando-os apenas em situações onde seja realmente necessário. Se a sua query pode ser realizada com apenas uma e não duas colunas no ORDER BY, então utilize apenas uma.

14. Evite o uso de cursores. Se realmente necessários, utilize temp tables com uma coluna identity e um WHILE para percorrer os registros através do seqüencial.

15. Liste apenas as colunas que precisa em suas querys, pois quanto maior o número de colunas em suas querys menor a performance. Use o “*” apenas quando realmente necessário.

16. Subquerys VS. Joins. Esta discussão é polêmica, porém é um concenso entre desenvolvedores que a grande maioria das subquerys pode ser substituída por JOINs. Porém dependendo da situação, uma subquery implementada com critério pode resultar uma uma performance aceitável. A única premissa que acredito ser bastante acertada, é evitar o uso de subquerys aninhadas, que degradam a performance demasiadamente.

17. O SELECT INTO funciona bem para tabelas pequena, porém pode ter resultados ruins para grandes datasets, pois um lock é criado no TEMPDB e outras querys que usam o TEMPDB para criação de objetos temporários, pois quando um novo objeto é criado é realizado um lock em SYSOBJECTS, SYSCOLUMNS e SYSINDEXES pois o SELECT...INTO copia não apenas os dados mas também a estrutura da tabela origem.

18. Procure usar variáveis de tabela e ao invés de temp tables. Temp tables podem fazer com que uma procedure recompile ao executar. Variáves do tipo table, foram criadas especificamente para evitar o recompile da query. Apesar disso, para uma query com um número demasiadamente grande de registros, as tabelas temporárias são a melhor opção.

19. Use os índices apropriados para a sua query, e procure evitar sempre que possível o TABLE SCAN do MS-SQL, utilizando preferencialmente os INDEX SCANS. Indexação do banco de dados deve ser algo criterioso pois os índices são responsáveis por 80% do tamanho dos banco de dados.

20. Utilize o profiler para determinar informações mais precisas sobre o CPU TIME, número de leituras físicas e do banco e informações relevantes para um futuro redimensionamento do servidor. Verifique principalmente o evento SP:Cachemiss do profiler, pois se ele estiver ocorrendo com freqüência, pode estar ocorrendo uma falta de memória no servidor.

Nenhum comentário:

Postar um comentário

Leave your comment here!