Ideia central
Boas práticas no SQL Server cobrem desde modelagem de dados e escrita de T-SQL até configuração de instância e segurança. Seguir essas práticas reduz retrabalho, melhora performance e evita problemas difíceis de diagnosticar em produção.
Modelagem e Design
Chaves primárias:
- Prefira colunas
INT IDENTITYouBIGINT IDENTITYcomo PK: menores, ordenadas, eficientes como chave de índice clustered - Evite GUIDs (
UNIQUEIDENTIFIER) como PKs clustered, pois causam fragmentação massiva por serem aleatórios. Se precisar de GUID, useNEWSEQUENTIALID()ou coloque a PK como não-clustered
-- Bom: INT IDENTITY como PK clustered
CREATE TABLE pedidos (
id INT IDENTITY(1,1) PRIMARY KEY,
cliente_id INT NOT NULL,
data DATETIME2 NOT NULL DEFAULT SYSDATETIME()
);
-- Cuidado: GUID como clustered PK gera fragmentação
-- Prefira newsequentialid() se GUID for obrigatório
CREATE TABLE items (
id UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
...
);Tipos de dados:
- Use
DATETIME2em vez deDATETIME, mais preciso, com menor custo de armazenamento e mais range de datas - Use
NVARCHARapenas quando Unicode for necessário;VARCHARé mais eficiente para dados ASCII - Defina tamanhos realistas:
VARCHAR(MAX)no lugar errado impede uso de índices - Evite
FLOAT/REALpara valores monetários; useDECIMAL(18,2)ouMONEY
Constraints:
- Sempre defina
NOT NULLexplicitamente quando o campo não pode ser nulo - Use constraints
CHECKpara validar domínios de dados no banco - Nomeie suas constraints para facilitar troubleshooting de erros de violação
ALTER TABLE pedidos ADD CONSTRAINT chk_status
CHECK (status IN ('pendente', 'aprovado', 'cancelado'));Escrita de T-SQL
Evite SELECT *: especifique sempre as colunas necessárias: reduz I/O, evita quebrar código quando colunas são adicionadas/removidas e permite ao otimizador usar index covering
-- Ruim
SELECT * FROM pedidos WHERE cliente_id = 100;
-- Bom
SELECT id, data, total, status FROM pedidos WHERE cliente_id = 100;Evite funções em colunas filtradas (SARGability): funções aplicadas na coluna do WHERE impedem uso de índices
-- Ruim: não usa índice em data_pedido
WHERE YEAR(data_pedido) = 2026
-- Bom: SARGable, usa índice
WHERE data_pedido >= '2026-01-01' AND data_pedido < '2027-01-01'
-- Ruim
WHERE UPPER(nome) = 'LOGAN'
-- Bom: use collation case-insensitive ou ajuste os dados
WHERE nome = 'Logan' -- se collation for CI (Case Insensitive)Prefira JOINs explícitos: nunca use sintaxe de join implícita (FROM a, b WHERE a.id = b.id)
Use transações com cuidado:
- Mantenha transações o mais curtas possível, pois transações longas bloqueiam outros processos
- Sempre trate erros com
TRY/CATCHe façaROLLBACKem caso de exceção
BEGIN TRY
BEGIN TRANSACTION;
UPDATE contas SET saldo = saldo - 500 WHERE id = 1;
UPDATE contas SET saldo = saldo + 500 WHERE id = 2;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
THROW; -- re-lança o erro
END CATCH;SET NOCOUNT ON em stored procedures: evita enviar mensagens de “N rows affected” para cada statement, reduzindo o tráfego de rede
CREATE PROCEDURE dbo.usp_processar_pedido @pedido_id INT
AS
BEGIN
SET NOCOUNT ON;
-- código aqui
END;Indexação
- Crie índices baseado nos padrões reais de acesso (queries do sistema), não em teoria
- Covering index: inclua colunas adicionais com
INCLUDEpara queries específicas
-- Covering index: busca por status, retorna id/data sem precisar buscar na tabela
CREATE INDEX idx_pedidos_status
ON dbo.pedidos (status)
INCLUDE (id, data, total);- Evite over-indexing, pois cada índice tem custo de manutenção em INSERT/UPDATE/DELETE
- Revise índices não usados:
sys.dm_db_index_usage_stats
Segurança
Princípio do menor privilégio: aplicações nunca devem usar sa ou roles como sysadmin/db_owner. Crie logins específicos com permissões mínimas necessárias.
Autenticação: prefira Windows Authentication (Kerberos/NTLM) em ambientes corporativos, mais seguro que SQL Authentication. Em containers/cloud, SQL Auth com senhas fortes é aceitável.
Senhas: SQL Logins devem ter CHECK_POLICY = ON para aplicar política de senha do Windows.
Dados sensíveis:
- Use Dynamic Data Masking para ocultar dados de usuários sem privilégio
- Use Transparent Data Encryption (TDE) para criptografar arquivos em repouso
Configurações de instância
-- Verificar configurações importantes
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- Max memory: NUNCA deixe em 0 (usa toda a RAM do servidor)
-- Deixe ao menos 4GB livres para o OS
EXEC sp_configure 'max server memory (MB)', 28672; -- ex: 28 GB
RECONFIGURE;
-- Cost threshold for parallelism: padrão é 5 (muito baixo)
-- Valores entre 25-50 são mais adequados para evitar paralelismo desnecessário
EXEC sp_configure 'cost threshold for parallelism', 35;
RECONFIGURE;
-- Max degree of parallelism: evite deixar no padrão 0 (usa todos os cores)
-- Regra geral: MAXDOP = número de cores por NUMA node, máximo 8
EXEC sp_configure 'max degree of parallelism', 4;
RECONFIGURE;Convenção de nomenclatura
Tabelas: PascalCase, singular (Pedido, ClientePJ)
Colunas: PascalCase ou snake_case (seja consistente)
SPs: usp_ + verbo + substantivo (usp_ProcessarPedido)
Functions: ufn_ prefixo
Views: v_ prefixo
Índices: idx_Tabela_Coluna(s)
PKs: pk_Tabela
FKs: fk_TabelaFilha_TabelaPai
CHECKs: chk_Tabela_Descricao
Conexões
- sqlserver-visao-geral - Arquitetura e contexto do SQL Server
- sqlserver-tuning-queries - Aplicar boas práticas na otimização de queries
- sqlserver-administracao - Boas práticas de administração (backup, segurança)
- db-relacional - Fundamentos de modelagem relacional