Você está na página 1de 15

1.

SUMÁRIO

2. DESENVOLVIMENTO DO DOCUMENTO........................................................................................................... 2
3. OBJETIVO DESTE DOCUMENTO ....................................................................................................................... 2
4. APLICAÇÃO ...................................................................................................................................................... 2
5. MÉTODOS DE INSPEÇÃO ................................................................................................................................. 2
6. DESENVOLVIMENTO........................................................................................................................................ 2
6.1. USO DE CURSOR EXPLÍCITO ............................................................................................................................. 2
6.2. USO DE LOOP E/OU CURSORES ANINHADOS .................................................................................................. 3
6.3. USO DA CLÁUSULA DISTINCT COM OPERADOR UNION .................................................................................. 3
6.4. USO DE OPERADORES: !=, !, NOT, IS NULL, LIKE ‘%VALOR’, LIKE ‘%VALOR%’ ................................................ 3
6.5. USO DE INLINE VIEW (SUBQUERY) .................................................................................................................. 4
6.6. USO DE LITERAIS NAS STATEMENTS T-SQL ..................................................................................................... 4
6.7. OCORRÊNCIA DE JOINS POR MEIO DE LINKED SERVERS ................................................................................. 4
6.8. USO DE FOR UPDATE ....................................................................................................................................... 4
6.9. OCORRÊNCIA DE COMANDO CASE / IF SEM ELSE (DEFAULT) ......................................................................... 4
6.10. OCORRÊNCIA DE EXCEPTION SEM RETURN EM FUNCTIONS .......................................................................... 5
6.11. OCORRÊNCIA DE EXCEPTION NÃO TRATADA NO CÓDIGO .............................................................................. 5
6.12. USO DE EXPRESSÃO COMPLEXA SEM PARÊNTESES () ..................................................................................... 5
6.13. USO DE IN AO INVÉS DE EXISTS ....................................................................................................................... 5
6.14. USO DE JOINS COM MAIS DE CINCO TABELAS ................................................................................................ 6
6.15. USO DE CURSOR COM SEM O COMANDO CLOSE EXPLÍCITO .......................................................................... 6
6.16. USO DESNECESSÁRIO DE UNION ..................................................................................................................... 6
6.17. USO DE SELECT SEM WHERE ........................................................................................................................... 6
6.18. USO DE FUNCTION EM COLUNA NA CLÁUSULA WHERE ................................................................................. 6
6.19. USO INEFICIENTE DOS RECURSOS COMO I/O, CPU, REDE E MEMÓRIA .......................................................... 7
6.20. COMPARAÇÃO ENTRE DATATYPES DIFERENTES (CONVERSÃO IMPLÍCITA) .................................................... 7
6.21. OCORRÊNCIA DE TABLE SCAN ......................................................................................................................... 7
6.22. USO DE SQL DINÂMICO AO INVÉS DE SQL ESTÁTICO ...................................................................................... 7
6.23. QUANTIDADE DE REGISTROS RETORNADOS É SUPERIOR A MIL NO SELECT .................................................. 8
6.24. USO EXCESSIVO DE COMENTÁRIOS ................................................................................................................ 8
6.25. USO DE INSTRUÇÃO DML SEM CLÁUSULA WHERE ......................................................................................... 8
6.26. USO DE “SELECT *” .......................................................................................................................................... 8
6.27. CONCESSÃO DE PRIVILÉGIOS EM OBJETOS ..................................................................................................... 8
6.28. USO DO DELETE PARA EXCLUIR TODOS OS REGISTROS DE UMA TABELA ....................................................... 9
6.29. OCORRÊNCIA DO NOME DO SCRIPT COM ESPAÇO EM BRANCO .................................................................... 9
6.30. OBJETOS DDL SEM OWNER PRECEDENTE AO NOME DO OBJETO .................................................................. 9
6.31. OCORRÊNCIA DE QUERY COM ALTA CARDINALIDADE .................................................................................. 10
6.32. OCORRÊNCIA DE PARTITION LIST ALL ........................................................................................................... 10
6.33. ORDER BY EM INSTRUÇÕES INSERT..SELECT OU SELECT INTO ..................................................................... 10
6.34. OCORRÊNCIA DE CRIAÇÃO DE TABELA TEMPORÁRIA “ON DEMAND” .......................................................... 10
6.35. USO DO HINT USE <DATABASE>.................................................................................................................... 10
6.36. USO DE TABELA DE MEMÓRIA ...................................................................................................................... 11
6.37. USO FORÇADO DE ÍNDICES ........................................................................................................................... 11
6.38. USO DE ÍNDICES COM CLÁUSULA INCLUDE .................................................................................................. 11
6.39. USO DE SET NOCOUNT ON EM STORED PRODECURES ................................................................................. 12
6.40. NÃO UTILIZAR O PREFIXO SP_PARA NOMEAR STORED PROCEDURES .......................................................... 12
6.41. USO DO COMANDO COUNT(*)...................................................................................................................... 12
6.42. SUBSTITUIR O USO DE CURSOR PELO COMANDO WHILE + TABELAS TEMPORÁRIAS OU VARIÁVEIS DO TIPO TABLE
13
7. RECOMENDAÇÕES NO DESENVOLVIMENTO DE PROCEDURES ..................................................................... 14
8. RECOMENDAÇÕES FINAIS ............................................................................................................................. 15
2. DESENVOLVIMENTO DO DOCUMENTO

Banco de Dados:
 Wiluey Queiroz de Sousa

3. OBJETIVO DESTE DOCUMENTO


Estabelecer procedimentos para padrões de codificação T-SQL, mantendo-os em conformidade, assegurando sua
uniformidade e coerência conforme regras apresentadas nesse documento.

4. APLICAÇÃO
A todo e qualquer sistema, interno ou externo desenvolvido para a Yasuda Marítima.

5. MÉTODOS DE INSPEÇÃO
Os objetos e scripts T-SQL serão avaliados seguindo as classes de inspeção. Caso algum não esteja em conformidade
com os Padrões de Codificação da Yasuda Marítima descritos, os mesmos serão encaminhados para ajustes com
eventuais recomendações de Performance.
As regras foram divididas em classes conforme o tipo de análise a ser aplicada conforme quadro abaixo:

Classe Enquadramento Regra

Submete os códigos a métricas que determinam a


A Melhores Práticas probabilidade de apresentar falhas relacionadas à
manutenção, desempenho ou processo.

Refere-se aos códigos cuja implantação pode proporcionar


B Manutenção maior chance de revisão no futuro, em razão de erros que
podem ocorrer quando o sistema estiver em produção.

Refere-se aos códigos que possuem risco alto de causar


degradação de desempenho, bem como inibir a
C Desempenho
escalabilidade do sistema quando a demanda no banco
aumentar, causando concorrência.

Refere-se ao modo como um script T-SQL foi escrito para


resolver um problema ou operação qualquer. Nessa classe
D Processo
analisam-se os recursos de banco utilizados, o algoritmo e
seus respectivos impactos no sistema.

As regras são apresentadas descrevendo a situação de violação, ou seja, informa qual é a falha a serem contornadas
com a aplicação da regra, bem como eventuais exceções, quando for aplicável.

6. DESENVOLVIMENTO

6.1. USO DE CURSOR EXPLÍCITO


Classe Regra
Essa regra é violada quando há uso da cláusula CURSOR ou TYPE CURSOR para
abertura de cursores desnecessários. Cursores explícitos consomem e retêm mais
D recursos do banco que cursores implícitos (cursores implícitos devem ser
utilizados sempre que possível). Essa regra não se aplica a iterações complexas, tal
que seja necessária à utilização de cursores explícitos.

6.2. USO DE LOOP E/OU CURSORES ANINHADOS


Classe Regra
Quando estruturas de laço são aninhadas, todas as instruções contidas no loop
interno serão executadas exponencialmente, ou seja, multiplicando a quantidade
de execuções do loop interno pelo loop externo. Supondo que haja no loop
interno uma consulta que efetue um Table Scan em uma tabela com uma grande
quantidade de registros, esse mesmo Table Scan será repetido quantas vezes
D
durar o processamento do laço, tanto interno quanto externo, gerando uma
perda grande de desempenho. Quando se utiliza esse mesmo princípio para o uso
de cursores, a quantidade de recursos de memória e I/O necessários, bem como a
quantidade de bloqueios, terá um aumento significativo. Uma alternativa ao uso
de cursores é usar variáveis do tipo TABLE.

6.3. USO DA CLÁUSULA DISTINCT COM OPERADOR UNION


Classe Regra
A cláusula DISTINCT e o operador UNION eliminam os registros duplicados. Por
esse motivo, o uso de ambos simultaneamente não faz sentido, já que haveria
A
consumo excessivo de recursos para realizar a mesma operação de forma
desnecessária.

6.4. USO DE OPERADORES: !=, !, NOT, IS NULL, LIKE ‘%VALOR’, LIKE ‘%VALOR%’
Classe Regra
A utilização dos operadores acima deve ser evitada, pois suprimem a utilização
de índices existentes nas colunas e normalmente precisam varrer toda a tabela
para satisfazer a condição, causando Table Scan. Essa regra não se aplica quando
A usada em colunas não indexadas.
Para busca de dados do tipo TEXT, VARCHAR, VARBINARY e XML, existem
processos do próprio SQL Server que otimizam este tipo de consulta. O DBA tem
total conhecimento e pode orientar o desenvolvedor no uso destas Features.
6.5. USO DE INLINE VIEW (SUBQUERY)
Classe Regra
Essa regra é violada quando há utilização de subqueries na cláusula FROM de um
script. Dependendo de como a query é resolvida pelo otimizador, a subquery
A poderá ser processada N vezes (N é a quantidade de registros retornados pela
query de fora), causando degradação de desempenho. A exceção ocorre quando
ela promove performance e não afeta a clareza e legibilidade do código.

6.6. USO DE LITERAIS NAS STATEMENTS T-SQL


Classe Regra
A capacidade de usar literais de cadeia de caracteres como aliases de coluna
aumentam as atividades de hard parse no banco, causando serialização,
C
contenção e perda de desempenho. Evite usar este recurso e substitua-o pela
cláusula AS.

6.7. OCORRÊNCIA DE JOINS POR MEIO DE LINKED SERVERS


Classe Regra
Em queries onde se faça necessária a leitura de dados através de um Linked
Server, procure carregar a quantidade necessária de dados em uma tabela
temporária local em tempo de execução e somente após isso realize as
C comparações por meio de JOIN referenciando a tabela temporária. É importante
avaliar também, além da quantidade de registros lidos, a quantidade de colunas
que serão necessárias, para que seja evitado o excesso de tráfego de dados e
consequente perda de desempenho.

6.8. USO DE FOR UPDATE


Classe Regra
Essa regra é violada quando há ocorrência da cláusula FOR UPDATE para
atualizar um bloco de registros, reduzindo a escalabilidade do sistema uma vez
que a concorrência é inibida. Quando há menos concorrência, há maior
C
contenção. Essa regra não se aplica quando as regras de negócio estão bem
definidas, tal que outros mecanismos de bloqueio não possam ser utilizados na
implantação, como ROWLOCK, UPDLOCK.

6.9. OCORRÊNCIA DE COMANDO CASE / IF SEM ELSE (DEFAULT)


Classe Regra
Essa regra é violada quando há uso de comandos CASE ou IF sem a condição
B DEFAULT. A utilização de ELSE nos statements CASE evita a ocorrência de
possíveis erros de lógica, caso a variável testada não esteja em conformidade
com os casos disponíveis.

6.10. OCORRÊNCIA DE EXCEPTION SEM RETURN EM FUNCTIONS


Classe Regra
Essa regra é violada quando da ausência de RETURN nas condições de exception
existentes – cujo corpo pertence a uma FUNCTION. Toda function deve retornar
B um valor, independente se o processamento é dirigido a um exception ou se
segue seu fluxo normal. A falta do RETURN em exception pode causar erros em
tempo de execução.

6.11. OCORRÊNCIA DE EXCEPTION NÃO TRATADA NO CÓDIGO


Classe Regra
Essa regra é violada quando não há tratamento no exception em procedimentos
B armazenados. O não tratamento de exceções de código pode causar erros em
tempo de execução.

6.12. USO DE EXPRESSÃO COMPLEXA SEM PARÊNTESES ()


Classe Regra
Essa regra é violada quando uma expressão complexa (que possui mais de 2
operadores aritméticos) estiver sem a devida especificação dos parênteses na
fórmula. Expressões complexas dificultam a legibilidade do código, podendo
A
ocasionar falta de compreensão, e consequentemente, erro no algoritmo do
programa. Essa regra não é válida quando as expressões possuem menos de 2
operadores aritméticos.

6.13. USO DE IN AO INVÉS DE EXISTS


Classe Regra
Essa regra é violada quando ocorre a utilização de IN ao invés de EXISTS para
verificar se determinado registro está contido em um conjunto de outros
registros. O uso de EXISTS tende a ser mais eficiente porque seu processamento
é interrompido quando um registro que satisfaz a condição é encontrado,
A
enquanto que o IN continua o processamento até o final, consumindo mais
recursos. A exceção ocorre quando o operador IN tende a ser melhor quando a
subquery submetida à query principal retorna menos registros que a query
principal. O operador EXISTS tende a ser melhor quando a subquery submetida à
query principal retorna mais registros que a query principal.

6.14. USO DE JOINS COM MAIS DE CINCO TABELAS


Classe Regra
Essa regra é violada quando uma query cuja quantidade de tabelas seja superior
a cinco. Quanto maior o número de tabelas, maior será a quantidade de
C iterações que a query terá de processar – maior consumo de recursos, como I/O,
memória e CPU. Essa regra não se aplica quando não houver outra forma de
implementação e/ou não apresentar melhores resultados de desempenho.

6.15. USO DE CURSOR COM SEM O COMANDO CLOSE EXPLÍCITO


Classe Regra
Essa regra é violada quando um cursor aberto sem o CLOSE explícito ao final de
todas as iterações. Se o cursor não é fechado explicitamente, todos os recursos
B
consumidos continuam retidos sem necessidade. A exceção ocorre quando
houver cursores abertos e fechados através do comando FOR.

6.16. USO DESNECESSÁRIO DE UNION


Classe Regra
Essa regra é violada quando há um operador UNION utilizado sem necessidade,
devido à existência de literais constantes em ambos os ResultSets. Esse comando
faz com que ocorram internamente ordenação e eliminação de registros
C
duplicados, o que acarretará processamento e uso de CPU desnecessários. Para
casos em que necessite utilizar junção de duas ou mais queries, utilizar o UNION
ALL.

6.17. USO DE SELECT SEM WHERE


Classe Regra
Essa regra é violada quando há uma statement SELECT sem cláusula WHERE. A
ausência da cláusula WHERE garante que a query será executada com TABLE
SCAN, ou INDEX SCAN. Essas operações de acesso devem ser todo o segmento
A
(tabela/índice) para resolver a query, causando maior consumo de recursos
como I/O, memória e CPU. Essa regra não se aplica com queries sobre tabelas de
parâmetros, ou sobre tabelas muito pequenas.

6.18. USO DE FUNCTION EM COLUNA NA CLÁUSULA WHERE


Classe Regra
Essa regra é violada com toda query cuja coluna na cláusula WHERE seja
submetida a uma função, e não exista algum índice baseado em função sobre
C esta coluna. O uso de funções sobre colunas na cláusula WHERE causam a
supressão de índices existentes, pois a função altera o valor da coluna. Esta
regra não se aplica quando a coluna restringida não for indexada.

6.19. USO INEFICIENTE DOS RECURSOS COMO I/O, CPU, REDE E MEMÓRIA
Classe Regra
Essa regra é violada quando um objeto DDL usa recursos de I/O, memória, CPU e
rede de forma ineficiente ou maiores do que o esperado. O uso ineficiente dos
D recursos da máquina pode causar o não atendimento ao tempo de resposta da
aplicação, que compromete sua operação e as necessidades do usuário final,
tornando a aplicação ineficiente.

6.20. COMPARAÇÃO ENTRE DATATYPES DIFERENTES (CONVERSÃO IMPLÍCITA)


Classe Regra
Essa regra é violada quando toda condição na cláusula WHERE cujos tipos dos
dados envolvidos sejam diferentes, causando maior consumo de recursos
durante processamento da query, uma vez que dependendo do tipo de
C
comparação, o SQL Server faz uso da conversão implícita e descarta o uso de
índices.
Exemplo: Comparar na cláusula WHERE uma coluna INT e uma coluna VARCHAR.

6.21. OCORRÊNCIA DE TABLE SCAN


Classe Regra
Essa regra é violada quando uma query possui TABLE SCAN em seu plano de
execução. A operação de acesso TABLE SCAN causa a leitura completa da tabela,
C consumindo muitos recursos de CPU, memória e principalmente I/O. Esta regra
não é aplicada em tabelas pequenas. O Scan é um processo demorado, e se
possível, deve ser substituído por Seek (Index Seek).

6.22. USO DE SQL DINÂMICO AO INVÉS DE SQL ESTÁTICO


Classe Regra
Essa regra é violada quando uma statement SQL cuja execução seja dinâmica e
não estática, através de recursos como EXEC @Varivael ou EXEC
SP_EXECUTESQL @Variavel. As atividades de parse no banco tendem a
B
aumentar quando ocorre a utilização de statements SQL dinâmicos. Além disto,
SQL dinâmico é interpretado, enquanto que SQL estático é executado do próprio
Kernel.
Caso haja necessidade de uso, recomendo alinhar previamente com o DBA.

6.23. QUANTIDADE DE REGISTROS RETORNADOS É SUPERIOR A MIL NO SELECT


Classe Regra
Essa regra é violada quando um statement SQL tem sua quantidade de registros
retornados superior a mil. Quanto maior é quantidade de registros a serem
C retornados, maior é o tráfego na rede, pois os registros são enviados ao Client
em lotes de N em N, e nunca tudo de uma vez. Essa regra não se aplica quando
os dados forem usados por sistemas de tomada de decisão.

6.24. USO EXCESSIVO DE COMENTÁRIOS


Classe Regra
Essa regra é violada quando um objeto T-SQL possuir mais de 30% das linhas
B referentes a comentários. O excesso de comentários dificulta a legibilidade do
código.

6.25. USO DE INSTRUÇÃO DML SEM CLÁUSULA WHERE


Classe Regra
Essa regra é violada quando há uma instrução DML (Update ou Delete) sem
A cláusula WHERE. Por segurança e boa prática, toda instrução DML deve conter
WHERE. Essa prática pode evitar perda de dados de maneira indesejada.

6.26. USO DE “SELECT *”


Classe Regra
Essa regra é violada quando uma instrução SQL contenha Select *. A utilização
do Select * não é seletiva, o ideal é especificar somente as colunas necessárias
para minimizar I/O e tráfego de rede. Quando esse comando é usado, o SQL
A Server consulta a database Master em busca do nome de todas as colunas, e
não diretamente na tabela.
Isso também causa o descarte do uso do índice, uma vez que o Query Optimizer
não identifica qual o melhor caminho a ser usado na busca.

6.27. CONCESSÃO DE PRIVILÉGIOS EM OBJETOS


Classe Regra
Toda concessão de privilégios deve ser feita diretamente à roles (com exceção
da role public), a qual um usuário deva pertencer. O grant to public implica
A
falhas de segurança e não se aplica as boas práticas, sendo o correto conceder
privilégios para roles da base de dados.

6.28. USO DO DELETE PARA EXCLUIR TODOS OS REGISTROS DE UMA TABELA


Classe Regra
Essa regra é violada quando há um comando que planeja apagar todos os
registros de uma tabela utilizando delete. Utilizar delete para apagar todos os
registros de uma tabela não é a maneira mais performática, pois ao apagar os
registros dessa forma, o SQL Server não libera o espaço que estava alocado para
os registros e deixa os índices altamente fragmentados e as estatísticas
C
desatualizadas. Isso significa que mesmo que a tabela não tenha nenhum
registro o espaço alocado anteriormente continuará em uso. Ao contrário do
delete o TRUNCATE além de apagar os registros da tabela libera o espaço que
estava alocado para os registros, provendo velocidade durante consultas a essa
tabela.

6.29. OCORRÊNCIA DO NOME DO SCRIPT COM ESPAÇO EM BRANCO


Classe Regra
Essa regra é violada quando um script T-SQL contém espaço em branco na sua
nomenclatura. Em ambiente de produção, os scripts são executados em lote e
A
de forma automática, e quando um espaço em branco é encontrado no nome do
script, o processo é abortado.

6.30. OBJETOS DDL SEM OWNER PRECEDENTE AO NOME DO OBJETO


Classe Regra
Essa regra é violada quando um script de criação de objeto no banco de dados
não está precedido pelo owner do objeto. Quando um script é executado sem o
A owner informado, assume-se o usuário logado no banco como proprietário do
objeto, o que pode levar à falha no momento de execução. Como exemplo, deve
adotar o padrão “owner.nomeobjeto”.
6.31. OCORRÊNCIA DE QUERY COM ALTA CARDINALIDADE
Classe Regra
Essa regra é violada quando um script T-SQL requisita dados de uma ou mais
tabelas e as colunas na cláusula Where são pouco seletivas e acabam lendo
muitos registros de forma desnecessária. Cardinalidade é um tipo de restrição
de integridade que modela regras de negócio que quantificam a quantidade
C
mínima e máxima de relacionamentos entre uma determinada entidade e outras
entidades distintas através de um relacionamento-tipo. Como métrica interna,
definiu-se que a cardinalidade não pode ser superior a 20% de leitura de uma
tabela.

6.32. OCORRÊNCIA DE PARTITION LIST ALL


Classe Regra
Essa regra é violada quando uma query faz leitura em uma tabela particionada e
o plano de acesso apresenta Partition List All, que ocorre quando o SQL Server
C
precisa fazer acesso a todas as partições existentes na tabela, causando
problemas de desempenho.

6.33. ORDER BY EM INSTRUÇÕES INSERT..SELECT OU SELECT INTO


Classe Regra
Evitar o uso deste artifício, especialmente quando houver apenas a necessidade
C de popular tabela temporária em tempo de execução a fim de trabalhar os
dados antes de efetuar atualizações em tabelas físicas.

6.34. OCORRÊNCIA DE CRIAÇÃO DE TABELA TEMPORÁRIA “ON DEMAND”


Classe Regra
Essa regra é violada quando há a necessidade de se criar uma tabela temporária
em tempo de execução, pois o SQL Server verifica cada tipo de dado em cada
C tabela envolvida e só depois cria a estrutura da tabela temporária. Esse processo
é custoso para o banco, e deve ser evitado criando-se previamente a tabela com
a estrutura desejada.

6.35. USO DO HINT USE <DATABASE>


Classe Regra
Todo script, seja ele DML ou DDL, deve informar o banco de dados a ser
utilizado. Dessa forma, evita-se a compilação de um objeto ou execução de um
C comando no database incorreto. Essa informação deve ser incluída na primeira
linha de cada script através o hint “USE <NomeBanco>” e na linha subsequente o
comando “GO”.

6.36. USO DE TABELA DE MEMÓRIA


Classe Regra
Devido à sua utilização estritamente local, tabelas criadas a partir de variável
tipo Table não consomem recursos para controle de bloqueios. A manipulação
de dados em variáveis tipos Table é mais eficiente porque essas operações são
minimamente locadas (um Rollback após um Insert não tem efeito em variáveis
do tipo Table). Em função do seu escopo local, a procedure que se utiliza de
variáveis tipos Table estão sujeitas a um número menor de recompilações
quando comparadas às tabelas temporárias. Deve ser observada também que
variáveis tipos Table não permitem alterações da estrutura da tabela, criação de
índices, criação de Constraints, criação e/ou atualização de estatísticas. Uma
C
variável do tipo Table não pode ser o destino de “INSERT EXEC” ou “SELECT
INTO” e só pode ser referenciada por um comando “SP_EXECUTESQL” se a
variável for criada. Seu uso também não é recomendável quando houver
necessidade de armazenamento superior a 80.000 registros. Variáveis tipo Table
também consomem recursos da TempDB – na verdade tanto tabelas
temporárias quanto variáveis tipo Table serão criadas em memória para
pequeno volume de dados. O diferencial das tabelas temporárias é o log
reduzido, o número baixo de recompilações e o ganho de desempenho com a
ausência do controle de bloqueios.

6.37. USO FORÇADO DE ÍNDICES


Classe Regra
Os hints para otimização de consultas (WITH FORCESSEK / WITH INDEX) podem
impedir que o otimizador escolha o plano de execução mais rápido, uma vez que
ele se baseia no custo. Os hints impedem que uma consulta ad hoc seja
A
qualificada na parametrização automática e no cache do plano de execução.
Para a necessidade do uso do hint, deve haver um alinhamento prévio com o
DBA.

6.38. USO DE ÍNDICES COM CLÁUSULA INCLUDE


Classe Regra
A partir do SQL Server 2005 é possível reduzir I/O de consultas utilizando a
cláusula INCLUDE, retirando as colunas que não serão utilizadas na busca binária
A do nível raiz e intermediário do índice, gerando um índice menor, com
consequente melhora no desempenho. As colunas definidas na cláusula
INCLUDE são acrescentadas ao nível folha do índice (leaf level). Outra vantagem
da cláusula INCLUDE é o limite de 1023 colunas, diferente da chave que contém
um limite muito menor de 16 colunas ou 900 bytes. Alguns tipos de dados que
não podem fazer parte da chave, como VARCHAR(MAX) podem compor o
INCLUDE. É possível utilizar esse recurso em todos os tipos de dados, com
exceção de TEXT, NTEXT e IMAGE. Não é possível utilizar esse recurso em índices
clusterizados.

6.39. USO DE SET NOCOUNT ON EM STORED PRODECURES


Classe Regra
Use a instrução SET NOCOUNT ON para evitar o SQL Server de enviar a
mensagem DONE_IN_PROC para cada instrução. Por exemplo, se você tem oito
operações em uma Stored Procedure, mesmo não usando todas, oito
C
mensagens são retornadas. Cada mensagem contém o número de linhas
afetadas pela respectiva declaração. Essa ação interna pode degradar o
desempenho.

6.40. NÃO UTILIZAR O PREFIXO SP_PARA NOMEAR STORED PROCEDURES


Classe Regra
Quando o otimizador encontra uma procedure com o prefixo SP_ a primeira
coisa que ele faz é buscá-la no banco de dados master.
A
Como você criou a procedure, ela não está lá, ao menos não deveria estar.
Evite a intercalação de DML e DDL em Stored procedures.

6.41. USO DO COMANDO COUNT(*)


Classe Regra
Esta instrução informa a quantidade de registros retornados em uma consulta.

SELECT COUNT(*) FROM Cliente

Porém não há a necessidade de utilização desta consulta, porque ao executá-la,


será contado um registro de cada vez. Para isto existem as tabelas ‘sysobjects’ e
D ‘sysindexes’. Com estas duas tabelas é possível obter muitas informações de
todos os objetos existentes no banco de dados.

SELECT
sysobjects.name AS [Nome da Tabela],
sysindexes.rowcnt AS [Qtde. de Registros]
FROM
sysobjects
INNER JOIN
sysindexes ON
sysindexes.id = sysobjects.id
WHERE
sysobjects.name = 'Cliente'
AND
sysindexes.indid = 1

6.42. SUBSTITUIR O USO DE CURSOR PELO COMANDO WHILE + TABELAS


TEMPORÁRIAS OU VARIÁVEIS DO TIPO TABLE
Classe Regra
DECLARE @VendorID Int,
@Name VarChar(80)
DECLARE Cur_Vendor CURSOR FOR
SELECT VendorID, Name
FROM Purchasing.Vendor
OPEN Cur_Vendor
FETCH NEXT FROM Cur_Vendor
INTO @VendorID, @Name

WHILE @@FETCH_STATUS = 0
BEGIN
C PRINT @Name

FETCH NEXT FROM Cur_Vendor


INTO @VendorID, @Name
END
CLOSE Cur_Vendor
DEALLOCATE Cur_Vendor
GO

DECLARE @ROWID Int,


@Name VarChar(80)
SET @ROWID = 0;
SELECT TOP 1
@ROWID = VendorID,
@Name = Name
FROM Purchasing.Vendor
WHERE VendorID > @ROWID
ORDER BY VendorID
WHILE @@ROWCOUNT > 0
BEGIN
PRINT @Name

SELECT TOP 1
@ROWID = VendorID,
@Name = Name
FROM Purchasing.Vendor
WHERE VendorID > @ROWID
ORDER BY VendorID
END
GO

7. RECOMENDAÇÕES NO DESENVOLVIMENTO DE PROCEDURES

 Sempre que uma procedure é executada o server envia para o Client o número de linhas afetadas
pela procedure, normalmente esta informação não é necessária. Desabilitando este
comportamento poderemos reduzir o trafego gerado pelo Server e o Client. Portanto sempre que
possível inclua o SET NOCOUNT ON no início de suas procedures. Pode ser que isso não gere muita
diferença em uma Procedure que efetua 01 INSERT, porém quando estamos falando de um loop
que efetua milhares/milhões de INSERTS a diferença de tráfego será relativa e podemos ter
gargalos.

 Deve-se usar a opção WITH ENCRYPTION e WITH RECOMPILE caso seja realmente necessário.
Lembre-se de que existem programas que conseguem descriptografar uma Procedure que está
criptografada no banco.

 Não é recomendável iniciar o nome das procedures com SP... Este prefixo é reservado para
procedures do sistema, sempre que você executa uma procedure que inicia com SP... O SQL irá
procurar a Procedure no banco Master e se ela não estiver lá então ele irá resolver o nome da
Procedure no banco atual. Evite este passo adicional simplesmente renomeando as procedures.

 Caso tenha que rodar algum código TSQL no meio da Procedure evite utilizar o EXEC ao invés disso
use a sp_ExecuteSQL pois ao contrário do EXEC a sp_ExecuteSQL irá compilar o SQL para gerar um
plano de execução para sua consulta, o quer dizer que caso o plano já tenha sido gerado na
próxima execução do código ele irá utilizar o plano que ficou em cachê, evitando a recompilação do
código a cada execução.

 Verificar o uso de FUNCTIONS. Caso exista alguma function envolvida no SQL analise bem a
consulta e verifique se é possível alterar a consulta para fazer um JOIN com a própria tabela ou
então até mesmo tabelas temporárias.
 Sempre que possível utilize “UNION ALL” ao invés de “UNION” pois o “UNION” gera um DISTINCT
que geralmente gera um ORDER BY, isso gerará um custo desnecessário comparado a concatenação
do “UNION ALL”.

8. RECOMENDAÇÕES FINAIS

Sempre que houver a possibilidade de um código processar uma quantidade de linhas muito diferentes
dependendo dos parâmetros de entrada (ou filtros) informados, não podemos correr o risco de deixar o
query processor (vide nota) executar a o código reutilizando um plano que possivelmente foi criado para
processar poucas linhas. Neste caso existem algumas opções que devem ser consideradas, são elas:

 OPTION (RECOMPILE) – Esta é a opção mais simples de ser utilizada, porém irá gerar a
recompilação (geração de um plano) do código todas as vezes que ela for utilizada.

 OPTION (OPTIMIZE FOR UNKNOWN) – Irá gerar um plano de execução baseado na densidade
(média de valores distintos) da coluna que está sendo filtrada

 OPTION (OPTIMIZE FOR (@parametro = <algum valor> )) – Com esta opção é possível especificar
um valor para garantir que um plano seja inicialmente criado com base neste valor, ignorando o
valor passado como parâmetro de entrada.

Dependendo da quantidade de vezes que a o código é executado, recomendo utilizar a opção OPTION
(RECOMPILE), porém testes devem ser realizados para analisar se o impacto de recompilar a consulta
realmente não pode ser evitado.

Como a procedure em questão utiliza a atribuição de variável, o OPTION (RECOMPILE) tem uma limitação
que não aplica a funcionalidade de Parameter Embedding Optimization para obter o ganho do plano mais
eficiente. Para resolver este problema, pode-se jogar os dados em uma tabela temporária e depois atribuir
o valor para a variável com base na própria temporária.

Você também pode gostar