O artigo será útil para o leitor
entender os conceitos de paralelismo, analisar planos paralelos, conhecer
detalhes do otimizador de consultas, determinar as corretas configurações de
uma instância do SQL Server e, naturalmente, ganhar uma sólida base para aplicar
em seu ambiente as melhores práticas, fazendo corretamente o troubleshooting ou
tuning de consultas paralelas.
Vivemos um período onde os processadores não evoluem mais tão rapidamente a cada novo ciclo de lançamento dos fabricantes. Em contrapartida, encontramos cada vez mais processadores em uma única máquina. Diante disso, é necessário que os programas passem a explorar o paralelismo em seu código, com múltiplas threads em execução, potencializando o uso do hardware à sua disposição.
O paralelismo possui um objetivo muito nobre, que é explorar a concorrência de processamento em um programa com o objetivo de resolver um problema em menos tempo.
Porém, é importante frisar que isto não significa que o uso de recursos será menor, pelo contrário, o tempo total de processamento (uso efetivo das CPUs) tende a ser maior, pois além da execução é necessário incluir no código mecanismos de sincronização das threads.
Atualmente é comum encontrarmos instâncias do SQL Server em servidores com 16, 32 ou mais núcleos (cores) de processamento. Diante desse cenário, é desejável que a engine possa explorar o paralelismo em seu código, ainda mais considerando que o SQL Server é licenciado por núcleo e não por outros fatores como, por exemplo, quantidade de memória.
E mesmo que o código do SQL Server tenha diversos trechos multi-thread, muitos deles não podem ser vistos ou são transparentes para nós, “usuários”. No entanto, existe um deles, assunto cerne deste artigo, onde podemos ver claramente a utilização de múltiplos núcleos de processamento: os planos de execução que possuem operadores paralelos.
Plano de execução paralelo
Definimos um plano paralelo como aquele composto por operadores que exploram o paralelismo em sua árvore de execução. Neste contexto, um conjunto de operadores paralelos é o que determina o que chamamos de zona paralela.
As zonas existem pelo fato do plano de execução nunca ser 100% paralelo, pois sempre o último operador deve ser não paralelo (serial) para que a engine possa retornar os registros da consulta a partir de uma única thread, chamada de coordenadora.
Dito isso, como primeiro exemplo deste artigo, faremos a comparação entre a execução de duas consultas, uma serial e outra paralela, com o intuito de apresentar como são processados os registros em um plano com zona paralela.
O detalhamento de como interpretar um plano de execução e seus operadores está além do escopo do artigo, porém é importante que se tenha o conhecimento do que são e como podem ser gerados através do SQL Server Management Studio. Você encontra um artigo sobre planos de execução na edição 119 da SQL Magazine.
Na Listagem 1 demonstramos uma consulta simples, que conta a quantidade de registros na tabela dbo.bigTransactionHistory fazendo uso da hint “MAXDOP 1”, que força o SQL Server a não utilizar paralelismo para esta consulta. O termo MAXDOP é bastante adotado por ser uma redução de MAX Degree Of Parallelism, ou grau máximo de paralelismo, e também será empregado ao longo deste artigo.
Listagem 1. Consulta simples, sem paralelismo.
USE AdventureWorks2012
GO
SET STATISTICS TIME ON;
SELECT COUNT(*) FROM dbo.bigTransactionHistory OPTION (MAXDOP 1);
GO
Como pode ser verificado na Figura 1, o plano de execução é simples. O SQL Server opta por percorrer um índice não cluster por completo (index scan), retornando cada um dos registros para ser contabilizado pelo próximo operador (stream aggregate), e por fim devolvendo o resultado para o cliente (o compute scalar não é relevante neste contexto).
Figura 1. Plano de execução simples, sem paralelismo.
Esse plano de execução tem um custo total de 150.456 e como saída gerada pelo comando SET STATISTICS TIME ON, t ...