(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa
SQL Server
SQL Server 2 min

Índices em SQL Server: columnstore vs rowstore para analytics e OLTP

João Barros 16 de August de 2024 2 min de leitura

Os índices são a principal alavanca de performance no SQL Server. A escolha entre rowstore (B-tree tradicional) e columnstore pode significar a diferença entre uma query de 30 segundos e 300 milissegundos.

Rowstore vs Columnstore

Rowstore (B-tree):
  - Armazena dados linha a linha
  - Ideal para OLTP: inserções/updates individuais, lookups por PK
  - Péssimo para agregações em tabelas grandes

Columnstore:
  - Armazena dados coluna a coluna (compressão 10x típica)
  - Ideal para OLAP/DW: agregações sobre milhões de linhas
  - Batch mode processing — processa 900 linhas de uma vez

Criar Clustered Columnstore Index

-- Tabela de factos no DW — columnstore é a escolha certa
CREATE CLUSTERED COLUMNSTORE INDEX CCI_FactVendas
ON dbo.FactVendas;

-- Verificar compressão conseguida
SELECT
    i.name,
    p.rows,
    SUM(a.total_pages) * 8 / 1024.0 AS size_mb,
    SUM(a.data_pages)  * 8 / 1024.0 AS data_mb
FROM sys.indexes i
JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_id
JOIN sys.allocation_units a ON p.partition_id = a.container_id
WHERE i.object_id = OBJECT_ID('dbo.FactVendas')
GROUP BY i.name, p.rows;

Nonclustered Columnstore para OLTP

-- Adicionar columnstore a tabela OLTP sem remover o clustered rowstore
CREATE NONCLUSTERED COLUMNSTORE INDEX NCCI_Vendas_Analytics
ON dbo.Vendas (data_venda, id_produto, valor, quantidade)
WHERE data_venda >= '2023-01-01';  -- índice filtrado

Índices filtrados

-- Apenas linhas activas — índice mais pequeno e rápido
CREATE NONCLUSTERED INDEX IX_Clientes_Activos
ON dbo.Clientes (nome, email)
WHERE estado = 'Activo';

Identificar índices em falta

SELECT
    migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) AS improvement_measure,
    'CREATE INDEX IX_' + OBJECT_NAME(mid.object_id) + '_' + REPLACE(mid.equality_columns, ', ', '_') AS suggested_index,
    mid.equality_columns, mid.inequality_columns, mid.included_columns
FROM sys.dm_db_missing_index_group_stats migs
JOIN sys.dm_db_missing_index_groups  mig  ON migs.group_handle = mig.index_group_handle
JOIN sys.dm_db_missing_index_details mid  ON mig.index_handle  = mid.index_handle
ORDER BY improvement_measure DESC;

Conclusão

Use clustered columnstore em todas as tabelas de factos do data warehouse. Para OLTP puro, use rowstore com índices cuidadosamente escolhidos. O sys.dm_db_missing_index_* é o seu melhor aliado para encontrar oportunidades rápidas de optimização.

Partilhar: