Vous êtes sur la page 1sur 14

www.devmedia.com.

br
[versão para impressão]
Link original: http://www.devmedia.com.br/articles/viewcomp.asp?comp=33484

Desvendando o SQL Server Columnstor


e Index
Este artigo apresenta o Columnstore Index. Através dele é possível
ganhar entre 4 e 100 vezes mais performance em atividades de
processamento massivo de informação.

Receba notificações :)
Fique por dentro
Índices do tipo columnstore se beneficiam de processamento rápido e armazenamento eficiente em
memória para prover uma capacidade de performance otimizada. Este artigo abordará a
funcionalidade Columnstore Index, que foi disponibilizada na versão 2012 e vem ganhando cada vez
mais importância, valor e absorção por parte do mercado a cada versão do produto. O conteúdo
apresentado é útil uma vez que, quando aplicados em ambientes de produção, índices columnstore
podem prover entre 4 e 100 vezes mais performance aos principais processos responsáveis pelo
processamento massivo de informação.

Índices do tipo columnstore são relativamente novos na plataforma SQL Server, sendo introduzidos na
versão 2012, mas a tecnologia aplicada nesta nova funcionalidade, conhecida como X-Velocity, já é
usada em outras ferramentas da própria Microsoft há algum tempo como, por exemplo, no PowerPivot
e no Tabular Mode para a ferramenta Analysis Services.

São oficialmente chamados pela Microsoft de “In-Memory Columnstore Indexes” por fazerem parte das
tecnologias de otimização da plataforma SQL Server que se beneficiam de processamento ultrarrápido
e armazenamento eficiente em memória para prover uma capacidade de performance ainda não vista
no produto.
O SQL Server foi o primeiro SGBD a incorporar nativamente este tipo de recurso e um dos principais
objetivos da introdução desta tecnologia é melhorar a performance das operações de leitura junto aos
ambientes de data warehouse, onde é comum a volumetria de dados atingir a escala de centenas de
gigabytes ou até mesmo alguns terabytes.

Os ganhos de performance obtidos com o uso dos índices colunares são tão grandes que não podemos
deixar de considerar a implementação deste recurso em bancos de dados OLTP também, onde
frequentemente temos relatórios que processam grandes quantidades de dados e/ou consomem
grande quantidade de tempo e recurso para serem processados.

O resultado e o feedback foram tão positivos que a Microsoft continuou investindo nesta funcionalidade
e na versão 2014 diversas otimizações foram realizadas, facilitando inclusive a aplicação deste recurso
nos mais diferentes cenários, sendo assim considerada uma importante e indispensável ferramenta
para se obter altos níveis de performance na plataforma SQL Server.

Os resultados de performance obtidos através da utilização dos índices colunares são possíveis devido
a uma combinação entre compressão de dados, algoritmos modernos e otimizados para os recursos de
hardware mais recentes, e paralelização eficiente em larga escala. Deste modo, quando aplicados no
ambiente, podem prover, dependendo das características dos objetos do banco de dados e das queries
neles executadas, entre 4 e 100 vezes mais performance aos principais processos responsáveis pelo
processamento massivo de informação.

Receba notificações :)
Todos os recursos disponíveis nas versões 2012 e 2014 dão ao profissional responsável pela
administração e/ou arquitetura de bancos de dados SQL Server um novo recurso com o objetivo de
melhorar a performance dos ambientes. Embora haja algumas limitações, que serão discutidas ao
longo desse artigo, há inúmeras alternativas para contorná-las e assim extrair melhor desempenho nos
processos executados na camada de bancos de dados.

Embora ainda não tenha sido lançado oficialmente, o SQL Server 2016 já anunciou algumas melhorias
a respeito dos índices colunares, novidades essas relacionadas principalmente à eliminação das
limitações existentes em seus predecessores, o que facilitará ainda mais a implementação deste
recurso em ambientes de produção com alta complexidade e grande exigência por performance.

Aplicações práticas
Um dos termos chave relacionados aos índices colunares é: tabelas extremamente grandes. São
nestes cenários em que é possível obter ganhos significativos. Atualmente, diversos tipos de bancos de
dados possuem objetos com dezenas de milhões ou bilhões de registros, tanto em ambientes OLTP
quanto em ambientes DW, destinados ao processamento de cubos OLAP.

Ambientes do tipo Data Warehouse são ótimos candidatos a se beneficiarem do uso de índices
colunares, pois neste tipo de cenário é comum a execução de queries que façam varreduras completas
(table ou index scans) e agregações (comandos Group By) em tabelas cuja quantidade de registros
geralmente ultrapassa a casa dos milhares ou até mesmo dos milhões de registros.
As queries comumente executadas em ambientes DW selecionam e calculam dados usando como
principal fonte de informação as chamadas “tabelas fato”, onde são armazenados os dados
relacionados à informação que se deseja obter (vendas de produtos, por exemplo). Estes processos
também envolvem JOINS com outras tabelas, visto que é necessário dar contexto à informação
resultante da operação (nome do produto ou período de vendas, por exemplo).

Este cenário faz com que, normalmente, a massa de dados consultada pelo processo seja considerável,
o que torna a query extremamente intensiva em termos de IO. É neste quesito que o índice colunar
agrega benefício: na eficiência da leitura dos dados.

Devido à sua capacidade de compressão e a arquitetura de armazenamento aplicada na estrutura


desse novo tipo de índice, o SQL Server pode ler os dados do disco, carregar em memória e processar
enormes volumes de informação mais facilmente do que seria com índices convencionais, baseados na
estrutura de uma B-Tree.

Non-Clustered Columnstore Index no SQL Server 2012/2014


A criação de um índice Non-Clustered Columnstore na versão 2012 ou superior do SQL Server é
extremamente simples. Em nosso teste inicial, iremos copiar uma tabela do banco de dados
“AdventureWorks2012” para uma base de dados isolada a fim de poder criar o índice que desejamos
sem nos preocuparmos com os índices já existentes, simplificando assim o entendimento a respeito

Receba notificações :)
dos índices colunares. A Figura 1 ilustra o processo mencionado.

Figura 1. Preparando a estrutura para criação do Columnstore Index.

Antes de criarmos o índice Columnstore, no entanto, temos alguns pontos de atenção relacionados aos
conceitos da tecnologia que devemos ter em mente:

· Diferentemente dos índices tradicionais, onde existem “key columns” e “included columns”, nos
índices colunares temos apenas o primeiro tipo. Como o índice não é organizado como uma árvore, as
colunas que fazem parte do índice têm um impacto completamente diferente do que é encontrado nos
índices clustered e non-clustered;
· Uma das limitações do SQL Server 2012 em relação aos índices colunares é em relação aos tipos de
dados suportados: uniqueidentifier e campos numéricos com escala e precisão muito altas não são
permitidos como, por exemplo, uma coluna numeric (38,6).

Ao considerar os dois pontos de atenção, especialmente o segundo deles, podemos perceber que
teremos limitações quanto à criação de um índice Columnstore em nossa tabela de testes, visto que
duas das colunas presentes no objeto foram criadas com tipos de dados que não são suportados pelos
índices colunares. A Figura 2 confirma esse fato.

Receba notificações :)

Figura 2. Definição da estrutura da tabela SalesOrderDetail_ColumnstoreIdx.

Isso fará com que nosso índice contemple apenas as colunas que possuem tipos de dados totalmente
suportados pelos Columnstore Indexes na versão 2012 do SQL Server. Assim, todas as queries que
usarem somente as colunas contempladas no índice colunar irão se beneficiar da performance provida
por ele, enquanto as demais ainda precisão acessar a heap (como no nosso caso) ou eventuais índices
clustered e non-clustered que existirem sobre a tabela.

O índice colunar pode ser criado tanto via Management Studio quanto via Transact-SQL. Para usar a
ferramenta, basta clicar com o botão direito do mouse no diretório de índices e depois selecionar a
opção Non-clustered Columnstore Index. Na tela que se abrirá, apresentada na Figura 3, basta
selecionar as colunas que você gostaria que fizessem parte do objeto e confirmar.
abrir imagem em nova janela

Figura 3. Criação do índice colunar através do SSMS.

Receba notificações :)
Além disso, existem algumas opções no processo de criação do índice colunar que permitem fazer
ajustes adicionais, tais como qual Filegroup onde ele será criado e quantas threads serão usadas em
seu processamento. Quando criamos o índice através da ferramenta SQL Server Management Studio,
estas configurações estão disponíveis nas abas Options e Storage.

Como mencionamos anteriormente, a criação do índice também pode ser feita diretamente através de
comandos DDL (Data Definition Language) em Transact-SQL e a sintaxe é extremamente parecida com
aquela encontrada no processo de criação dos índices tradicionais, como podemos verificar no
comando apresentado na Listagem 1, equivalente ao índice criado por nós na Figura 3.

Listagem 1. Comando DDL para criação de índice Columnstore.

CREATE COLUMNSTORE INDEX IX_Columnstore_001


ON SalesOrderDetail_ColumnstoreIdx
(
SalesOrderID
,SalesOrderDetailID
,CarrierTrackingNumber
,OrderQty
,ProductID
,SpecialOfferID
,UnitPrice
,UnitPriceDiscount
,ModifiedDate
)
WITH (MAXDOP = 1)
ON [PRIMARY]

Repare no comando que a palavra-chave “Columnstore” está presente entre os comandos “CREATE” e
“INDEX”, indicando que nosso índice será colunar. Note também que não temos as duas colunas com
tipos de dados não suportados por este recurso. No final do arquivo ainda possuímos a opção MAXDOP,
já mencionada anteriormente, que controla quantas threads serão usadas durante a criação do índice,
e finalmente, temos a indicação de qual Filegroup receberá o índice colunar que estamos criando.

Neste momento vale ressaltar que depois de criado o índice, fica impossível modificar quaisquer dados
presentes na tabela diretamente através de comandos DML (Data Manipulation Language). A principal
alternativa é usar os recursos oferecidos pelo particionamento para inserir dados em uma tabela
intermediária e depois realizar um procedimento chamado “SWITCH” dos dados para que o objeto
onde o Columnstore existe possa receber os dados e disponibilizá-los para consulta.

Clustered Columnstore Index no SQL Server 2014


O SQL Server 2014 também nos oferece a possibilidade de criar um Non-Clustered Columnstore Index,
da mesma forma que seu predecessor, tendo basicamente as mesmas limitações quanto a tornar a
tabela read-only, por exemplo. A grande novidade fica por conta da disponibilidade de um novo tipo de
índice colunar: o Clustered.

Receba notificações :)
O Clustered Columnstore Index possui maior abrangência quanto aos tipos de dados suportados por
ele, possui uma estrutura de funcionamento interna totalmente diferente dos Non-Clustered
Columnstore Indexes e, acima de tudo, permite atualizações diretas à tabela através de DML, sendo
assim um recurso invisível ao usuário e à aplicação em termos de facilidade de uso e implementação
da solução.

A criação do Clustered Columnstore Index no SQL Server 2014 também é extremamente simples. Para
demonstrarmos o passo a passo, iremos duplicar a tabela SalesOrderDetail do banco de dados
AdventureWorks2014, basicamente o mesmo procedimento que fizemos no exemplo do Non-clustered
Columnstore Index do SQL Server 2012. A Figura 4 exibe o que foi feito para preparar nosso
laboratório.
Figura 4. Preparando a estrutura para criar o Clustered Columnstore Index.

Uma vez criada a tabela que usaremos de exemplo, podemos criar o índice colunar do tipo Clustered.
Para isso, podemos usar o comando a seguir:

CREATE CLUSTERED COLUMNSTORE INDEX IX_CLUSTEREDCOLUMNSTORE_001


ON SalesOrderDetail_ClusteredColumnstore

Repare que na criação do Clustered Columnstore Index não é necessário informar quais colunas farão

Receba notificações :)
parte da estrutura, visto que assim como os índices tradicionais do tipo clustered, todos os campos
farão parte do objeto.

Outro ponto interessante a destacar é que, como pudemos ver, não tivemos complicações quanto aos
tipos de dados suportados pelo índice colunar. Essa é uma melhoria dos Clustered Columnstore
Indexes do SQL Server 2014 em relação aos disponíveis desde a versão 2012. Tipos de dados como
uniqueidentifier e numeric com escala e precisão muito grandes não são mais uma limitação dos
índices colunares, podendo assim ser contemplados na criação do objeto.

A Figura 5 exibe a estrutura da tabela criada anteriormente, que agora possui um Clustered
Columnstore Index. Observem que as colunas presentes na versão 2014 são exatamente iguais às
encontradas na versão 2012, incluindo as colunas LineTotal e rowguid, que na versão 2012 tiveram de
ser desconsideradas para que o Non-Clustered Columnstore Index fosse criado com sucesso.
Receba notificações :)
Figura 5. Estrutura da tabela teste usada no SQL Server 2014.

Uma das principais limitações associadas ao Clustered Columnstore Index é que este recurso não é
compatível com nenhum outro tipo de índice. Isso significa que, se a tabela possuir qualquer índice já
criado, ele deverá ser excluído para que o índice colunar do tipo Clustered seja criado, não podendo
serem recriados posteriormente também.

Criação do Columnstore Index


O processo de criação de um índice colunar é extremamente intensivo quanto ao consumo de
memória, porém, a quantidade de recursos que ele consome em nada depende do tamanho da tabela
e sim de outros fatores como, por exemplo, de quantas colunas farão parte do índice. A fórmula a
seguir pode ajudar a prever de maneira aproximada quanto de memória será consumido durante a
criação de um Columnstore Index:

Memória necessária = (4,2 * Quantidade de colunas + 68) * (Nível de paralelismo) + (Quantidade de colunas
O valor resultante desta fórmula (disponibilizada por Dmitri Korotkevitch – MCM e MVP SQL Server)
pode auxiliar no planejamento de quanto recurso será requisitado pela criação do índice. Ter
consciência do consumo de memória é importante porque se não houver recurso disponível para o
processamento do índice colunar, o processo inteiro falhará.

Há duas formas de contornar possíveis problemas relacionados à memória insuficiente: a primeira


delas é reduzindo a quantidade de threads disponíveis para o processamento usando o parâmetro
MAX_DOP. Essa opção reduzirá o consumo de memória, mas fará com que o processamento necessite
de mais tempo para ser concluído. A segunda alternativa é mudar a configuração da propriedade
REQUEST_MAX_MEMORY_GRANT_PERCENT no Resource Governor do SQL Server, mas essa opção
afetará os demais processos em execução no servidor.

Limitações adicionais
Além das limitações que foram mencionadas anteriormente, os índices colunares não podem ser
criados sobre colunas que possuem a propriedade SPARSE ativada ou em colunas calculadas. Views
indexadas também não são capazes de receber um Columnstore Index.

Outra limitação é que em ambas as versões (2012 e 2014) do SQL Server, os seguintes tipos de dados
não são suportados:

· BINARY;

Receba notificações :)
· VARBINARY;

· (N) TEXT;

· IMAGE;

· (N) VARCHAR(MAX);

· TIMESTAMP;

· Tipos de dados CLR;

· SQL_VARIANT;

· XML.

No entanto, na versão 2014 os tipos de dados a seguir passaram a ser compatíveis com os índices
colunares, sendo que na versão 2012 eles não permitiam a criação do Columnstore Index:

· UniqueIdentifier;

· DECIMAL e NUMERIC com precisão superior a 18 dígitos;

· DATETIMEOFFSET com precisão superior a 2.


Armazenamento
O armazenamento realizado pelos índices Columnstore é diferente do que é feito pelos índices
Rowstore, pois ao invés de armazenar todas as colunas de um determinado registro juntas na mesma
página, o que é feito pelos índices baseados em B-Trees, os índices colunares organizam os dados
agrupando todos os valores da mesma coluna juntos, mantendo com eles apenas uma informação
adicional que permite rastrear qual o registro que aquele valor pertence.

A Figura 6 ilustra a organização de um índice clustered Rowstore criado sobre uma tabela que possui
as colunas código, usada como chave do índice, e outras duas chamadas Cidade e Estado. Lembrando
que as colunas Cidade e Estado, mesmo não fazendo parte da chave do índice, são armazenadas no
nível folha do nosso índice, pois ele é do tipo clustered, o que faz com que todas as colunas existentes
na tabela sejam armazenadas no nível folha dele.

Receba notificações :)
abrir imagem em nova janela

Figura 6. Estrutura de um índice clustered Rowstore.

O formato de armazenamento usado pelos índices colunares faz com que os dados sejam armazenados
diferentemente do apresentado pela Figura 6. Cada coluna é organizada em um grupo próprio,
contendo valores para aproximadamente 1 milhão de registros, formando assim um conjunto de dados
denominado segmento. Um grupo de segmentos que armazenam colunas diferentes para os mesmos
registros é chamado de RowGroup, conforme ilustrado na Figura 7.
Figura 7. Organização dos dados em um Columnstore Index.

Receba notificações :)
Armazenando os dados de forma colunar, os índices Columnstore podem se beneficiar de uma taxa de
compressão muito acima da fornecida pela funcionalidade Data Compression, pois armazenar todos os
dados de uma determinada coluna juntos aumenta a probabilidade de se encontrar valores repetidos,
facilitando assim o armazenamento único daquela informação. Isto também traz economia de espaço
em disco e em memória, o que aumenta a performance da solução.

A quantidade de registros presentes em cada segmento é de aproximadamente 1 milhão, mas o valor


exato depende de alguns fatores como, por exemplo, o nível de paralelismo usado na criação, o uso de
particionamento de dados no índice colunar em questão e também da quantidade de registros
existentes na tabela onde o objeto está sendo criado.

É interessante mencionar que, devido a seu método de armazenamento baseado no agrupamento dos
dados por coluna ao invés de registros, não há significância alguma na ordenação das colunas no
comando de criação do índice, diferentemente dos índices Rowstores, onde a posição das colunas
dentro do objeto interfere diretamente em sua performance e usabilidade.

Batch mode
A performance elevada obtida pelos índices Columnstore também é possível devido a outra
característica do produto que eleva e muito a capacidade de processamento dos dados: o Batch Mode.
Este modelo de processamento é aplicado na execução das queries que fazem uso dos índices
colunares justamente por tratar de melhorar a manipulação de dados em massa e permitir que uma
maior quantidade de dados seja processada por vez.

Internamente, o modelo de processamento Batch Mode permite que o SQL Server processe dados em
grupos de registros, ao invés de lidar com uma linha por vez, como é feito no processamento dos
dados que passam de um operador para outro durante a execução da maioria das queries submetidas
ao SGBD. Uma das vantagens deste modo é que os dados, ao invés de serem transmitidos entre os
operadores presentes no plano de execução, são reutilizados a cada etapa do processo. Para definir
quais registros ainda são válidos na execução daquela query, o SQL Server usa uma marca d’água.
Desta forma, dados excluídos por filtros são eliminados apenas logicamente das etapas subsequentes.

O tamanho do grupo de registros que é processado no Batch Mode é flexível para permitir que possa
ser armazenado na memória cache do processador, assim reduzindo a necessidade de solicitar dados
de recursos externos ao CPU, como memória e/ou disco. Deste modo, operações como agregações
obtêm melhor desempenho, visto que o SQL Server passa a calcular o resultado considerando o grupo
de registros como um todo e não apenas um registro de cada vez.

Carga de dados

Receba notificações :)
Não é possível inserir, atualizar ou excluir dados em objetos que possuem um Non-clustered
Columnstore Index, porém, como sua principal aplicação é relacionada a ambientes onde os dados em
sua grande maioria são estáticos – como bancos de dados DW –, o esforço para excluir o índice e criar
novamente toda vez que cargas de dados forem realizadas não é suficientemente grande para que
essa estratégia seja desconsiderada, sendo assim uma boa opção para a maioria dos cenários onde
esse tipo de índice é criado.

Outra alternativa para realizar a carga de dados pode ser a utilização do particionamento de tabelas,
que através do comando SWITCH permite que novos registros sejam adicionados a objetos onde um
índice colunar já existe.

Para realização do procedimento de carga através de particionamento, basicamente é necessária a


criação de uma tabela stage com a mesma estrutura do objeto onde os dados deverão ser inseridos e
onde o índice colunar já existe, depois inserir os registros nesta segunda estrutura, criar um
Columnstore Index exatamente igual ao já existente na tabela final e finalmente executar o comando
SWITCH para “mesclar” as duas tabelas.
Por fim, outra possível estratégia para contornar esta limitação dos Non-clustered Columnstore
Indexes é a utilização de duas tabelas diferentes, uma para os dados históricos, onde o índice colunar
pode ser criado normalmente, e outra para armazenar os dados recentes, onde não há índice colunar.
Com as duas estruturas em mãos, é possível combinar os resultados através de um SELECT com
UNION.

O que vem por aí na versão 2016


O SQL Server 2016 já está disponível para testes e já há uma boa quantidade de material disponível
na internet sobre suas melhorias e novas funcionalidades. Dentre as diversas novidades associadas à
nova versão do produto, algumas delas são relativas aos índices colunares. Podemos destacar entre as
mais significativas melhorias, a possibilidade de criar índices colunares sobre tabelas In-Memory (BOX
1), o que até então não era possível.

BOX 1. In-Memory

É uma tecnologia do SQL Server disponibilizada na versão 2014 e seu objetivo é permitir a criação
de tabelas otimizadas que sejam capazes de ficar armazenadas em memória todo o tempo, dando
assim maior desempenho às consultas que acessam aquele objeto, pois além de não haver necessi
dade de realizar leituras em disco, todos os mecanismos de controle do SQL Server em relação a l
ocks e latches são gerenciados de forma diferenciada, eliminando assim algumas etapas no acesso

Receba notificações :)
aos dados.

Outra novidade é que a compatibilidade entre Clustered Columnstore Index e Rowstore Non-Clustered
Indexes será uma realidade, eliminando uma das limitações da versão 2014 já mencionadas. Essa
possibilidade permitirá o uso de índices de ambos os tipos na mesma tabela, viabilizando a indexação
do objeto de forma mais flexível.

O cenário inverso ao mencionado também será uma novidade da versão 2016: criar Non-Clustered
Columnstore Indexes em tabelas que já possuem Rowstore Clustered Index e que tenham até mesmo
índices Rowstore auxiliares do tipo Non-Clustered.

O artigo discorreu sobre alguns dos principais conceitos acerca dos índices colunares, explicando parte
da funcionalidade e arquitetura encontradas neste recurso. O objetivo foi apresentar conceitualmente
as vantagens e cenários possíveis onde essa opção pode ser aplicada a fim de se obter melhor
performance na execução de queries sobre tabelas com grandes quantidades de registros, situação
frequentemente encontrada em ambientes DW.

Foram apresentados também exemplos práticos de criação dos índices colunares para que os leitores
possam ver algumas das considerações que devem ser relevadas durante as etapas de planejamento e
criação da estrutura, evitando deste modo que a aplicação desse recurso seja feita fora dos padrões e
melhores práticas existentes.
Embora o objetivo do artigo não seja a aplicação de testes de performance, é possível perceber que
devido aos conceitos e tecnologias aplicadas pela Microsoft junto aos índices colunares, os benefícios
associados aos ganhos de performance podem ser significativos para embasar testes detalhados da
solução em situações mais próximas do cenário de negócio da empresa, justificando sua consideração
no momento de iniciar um projeto de melhoria de performance, desenvolvimento de uma nova
aplicação ou mesmo refatoração do banco de dados.

Referências

Livro – SQL Server 2012 Bible


http://www.wiley.com/WileyCDA/WileyTitle/productCd-1118106873.html

Livro – Pro SQL Server Internals


http://www.apress.com/9781430259626

Blog – Niko Neugebauer


http://www.nikoport.com/2013/07/05/
clustered-columnstore-indexes-part-1-intro/

Blog – DataEX
http://dataexblog.azurewebsites.net/

Receba notificações :)
Site – SQL Server Central - Stairway to Columnstore Indexes
http://www.sqlservercentral.com/stairway/121631/

por Felipe de Assis


Revista SQL Magazine lover