Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Estatísticas Incrementais do SQL Server 2014


Benjamin Nevarez é um consultor independente com sede em Los Angeles, Califórnia, especializado em ajuste e otimização de consultas do SQL Server. Ele é o autor de “SQL Server 2014 Query Tuning &Optimization” e “Inside the SQL Server Query Optimizer” e coautor de “SQL Server 2012 Internals”. Com mais de 20 anos de experiência em bancos de dados relacionais, Benjamin também foi palestrante em muitas conferências do SQL Server, incluindo o PASS Summit, SQL Server Connections e SQLBits. O blog de Benjamin pode ser encontrado em http://www.benjaminnevarez.com e ele também pode ser contatado por e-mail em admin em benjaminnevarez ponto com e no twitter em @BenjaminNevarez.

Um grande problema com a atualização de estatísticas em tabelas grandes no SQL Server é que a tabela inteira sempre precisa ser verificada, por exemplo, ao usar o WITH FULLSCAN opção, mesmo que apenas os dados recentes tenham sido alterados. Isso também é verdade ao usar o particionamento:mesmo que apenas a partição mais recente tenha sido alterada desde a última vez que as estatísticas foram atualizadas, atualizar as estatísticas novamente é necessário para verificar a tabela inteira, incluindo todas as partições que não foram alteradas. Estatísticas incrementais, um novo recurso do SQL Server 2014, podem ajudar com esse problema.

Usando estatísticas incrementais, você pode atualizar apenas a partição ou partições necessárias e as informações dessas partições serão mescladas com as informações existentes para criar o objeto de estatísticas final. Outra vantagem das estatísticas incrementais é que a porcentagem de alterações de dados necessárias para acionar uma atualização automática de estatísticas agora funciona no nível da partição, o que basicamente significa que agora apenas 20% das linhas alteradas (alterações na coluna de estatísticas principal) por partição são necessárias. Infelizmente, o histograma ainda está limitado a 200 etapas para todo o objeto de estatísticas nesta versão do SQL Server.

Vejamos um exemplo de como você pode atualizar estatísticas em um nível de partição para explorar seu comportamento pelo menos a partir do SQL Server 2014 CTP2. Primeiro precisamos criar uma tabela particionada usando o banco de dados AdventureWorks2012:
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME)
AS RANGE RIGHT FOR VALUES 
(
   '20071001', '20071101', '20071201', '20080101', 
   '20080201', '20080301', '20080401', '20080501', 
   '20080601', '20080701', '20080801'
);
GO
 
CREATE PARTITION SCHEME TransactionsPS1 AS PARTITION TransactionRangePF1 TO 
(
  [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], 
  [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], [PRIMARY], 
  [PRIMARY], [PRIMARY], [PRIMARY]
);
GO
 
CREATE TABLE dbo.TransactionHistory 
(
  TransactionID        INT      NOT NULL, -- not bothering with IDENTITY here
  ProductID            INT      NOT NULL,
  ReferenceOrderID     INT      NOT NULL,
  ReferenceOrderLineID INT      NOT NULL DEFAULT (0),
  TransactionDate      DATETIME NOT NULL DEFAULT (GETDATE()),
  TransactionType      NCHAR(1) NOT NULL,
  Quantity             INT      NOT NULL,
  ActualCost           MONEY    NOT NULL,
  ModifiedDate         DATETIME NOT NULL DEFAULT (GETDATE()),
  CONSTRAINT CK_TransactionType 
    CHECK (UPPER(TransactionType) IN (N'W', N'S', N'P'))
) 
ON TransactionsPS1 (TransactionDate);
GO

Observação:para obter detalhes sobre particionamento e CREATE PARTITION FUNCTION / SCHEME instruções, consulte Tabelas e Índices Particionados nos Manuais Online.

Atualmente temos dados para preencher 12 partições. Vamos começar primeiro preenchendo apenas 11.
INSERT INTO dbo.TransactionHistory
SELECT * FROM Production.TransactionHistory
WHERE TransactionDate < '2008-08-01';

Se necessário, você pode usar a seguinte instrução para inspecionar o conteúdo das partições:
SELECT * FROM sys.partitions
  WHERE object_id = OBJECT_ID('dbo.TransactionHistory');

Vamos criar um objeto de estatísticas incrementais usando o CREATE STATISTICS instrução com o novo INCREMENTAL cláusula definida como ON (OFF é o padrão):
CREATE STATISTICS incrstats ON dbo.TransactionHistory(TransactionDate) 
  WITH FULLSCAN, INCREMENTAL = ON;

Você também pode criar estatísticas incrementais ao criar um índice usando o novo STATISTICS_INCREMENTAL cláusula do CREATE INDEX demonstração.

Você pode inspecionar o objeto de estatísticas criado usando DBCC :
DBCC SHOW_STATISTICS('dbo.TransactionHistory', incrstats);

Entre outras coisas, você notará que o histograma tem 200 passos (apenas os 3 últimos mostrados aqui):
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS
198 2008-07-25 00:00:00.000 187 100 2
199 2008-07-27 00:00:00.000 103 101 1
200 2008-07-31 00:00:00.000 281 131 3

Resultados iniciais do DBCC

Então já temos o máximo de passos em um objeto de estatística. O que aconteceria se você adicionasse dados a uma nova partição? Vamos adicionar dados à partição 12:
INSERT INTO dbo.TransactionHistory 
SELECT * FROM Production.TransactionHistory 
WHERE TransactionDate >= '2008-08-01';

Agora, atualizamos o objeto de estatísticas usando a seguinte instrução:
UPDATE STATISTICS dbo.TransactionHistory(incrstats) 
  WITH RESAMPLE ON PARTITIONS(12);

Observe a nova sintaxe que especifica a partição, onde você pode especificar várias partições, separadas por vírgula. O UPDATE STATISTICS A instrução lê as partições especificadas e, em seguida, mescla seus resultados com o objeto de estatística existente para criar as estatísticas globais. Observe o RESAMPLE cláusula; isso é necessário, pois as estatísticas de partição precisam ter as mesmas taxas de amostragem a serem mescladas para criar as estatísticas globais. Embora apenas a partição especificada tenha sido verificada, você pode ver que o SQL Server reorganizou o histograma. As últimas três etapas agora mostram dados para a partição adicionada. Você também pode comparar o original com o novo histograma para outras pequenas diferenças:
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS
197 2008-07-31 00:00:00.000 150 131 2
198 2008-08-12 00:00:00.000 300 36 9
199 2008-08-22 00:00:00.000 229 43 7
200 2008-09-03 00:00:00.000 363 37 11

Resultados do DBCC após a atualização incremental

Se por algum motivo você quiser desabilitar as estatísticas incrementais, você pode usar a seguinte instrução para voltar ao comportamento original (ou, opcionalmente, apenas descartar o objeto de estatísticas e criar um novo).
UPDATE STATISTICS dbo.TransactionHistory(incrstats) 
  WITH FULLSCAN, INCREMENTAL = OFF;

Após desabilitar as estatísticas incrementais, tentar atualizar uma partição conforme mostrado anteriormente retornará a seguinte mensagem de erro:
Msg 9111, Level 16, State 1
UPDATE STATISTICS ON PARTITIONS sintaxe não é suportada para estatísticas não incrementais.
Por fim, você também pode habilitar estatísticas incrementais para suas estatísticas automáticas no nível do banco de dados, se necessário. Isso requer o INCREMENTAL = ON cláusula no ALTER DATABASE e obviamente também requer AUTO_CREATE_STATISTICS definido como ON .