Temos um grande banco de dados particionado do SQL Server utilizando estatísticas incrementais. Todos os índices são particionados alinhados. Quando tentamos reconstruir uma partição online por partição, todas as estatísticas desaparecem após a reconstrução do índice.
Abaixo está um script para replicar o problema no SQL Server 2014 com o banco de dados AdventureWorks2014.
--Example against AdventureWorks2014 Database
CREATE PARTITION FUNCTION TransactionRangePF1 (DATETIME)
AS RANGE RIGHT FOR VALUES
(
'20130501', '20130601', '20130701', '20130801',
'20130901', '20131001', '20131101', '20131201',
'20140101', '20140201', '20140301'
);
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);
INSERT INTO dbo.TransactionHistory
SELECT * FROM Production.TransactionHistory
-- SELECT * FROM sys.partitions
-- WHERE object_id = OBJECT_ID('dbo.TransactionHistory');
CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId)
WITH (DATA_COMPRESSION = ROW, STATISTICS_INCREMENTAL=ON)
ON TransactionsPS1 (TransactionDate)
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Stats are avialable'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)
PRINT 'After online index rebuild by partition stats are now gone'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Rebuild the stats with a rebuild for all paritions (this works)'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = ALL WITH (ONLINE = ON , DATA_COMPRESSION = ROW,
STATISTICS_INCREMENTAL = ON)
PRINT 'Stats are back'
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT 'Works correctly for an offline rebuild by partition'
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = OFF , DATA_COMPRESSION = ROW)
--stats still there
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
ALTER INDEX [IDX_ProductId] ON [dbo].[TransactionHistory] REBUILD
PARTITION = 9 WITH (ONLINE = ON , DATA_COMPRESSION = ROW)
DBCC SHOW_STATISTICS('dbo.TransactionHistory', IDX_ProductId);
PRINT' stats are gone!!!!!!'
Como mostrado, não podemos reconstruir índices partindo online sem perder todas as estatísticas do índice. Este é um grande problema de manutenção para nós. Parece quase que a opção incremental de estatísticas precisa fazer parte da sintaxe de reconstrução de índice único ou a opção online precisa lidar adequadamente com ela, como faz a opção offline.
Informe-me se estiver faltando alguma coisa?
Atualizações:
Quanto à nossa necessidade de estatísticas incrementais: estamos particionando em um ID de cliente interno e não em uma data. Portanto, quando um novo cliente é trazido (grande carregamento de dados), podemos simplesmente atualizar as estatísticas da partição e evitar rapidamente qualquer plano feio que esteja sendo criado para esse novo cliente. Acho que vou arquivá-lo na Microsoft como um bug e ver o que eles têm a dizer e seguir a solução de apenas re-amostrar as estatísticas dessa partição.
Conecte o relatório de erro:
As estatísticas desaparecem após a reconstrução do índice online com estatísticas incrementais
Atualização: A Microsoft confirmou que é um bug.
Respostas:
Não tenho certeza se é um bug, por si só, mas é definitivamente uma ocorrência interessante. As recriações de partições online são novas no SQL Server 2014, portanto, pode haver alguns elementos internos a serem resolvidos.
Aqui está a minha melhor explicação para você. As estatísticas incrementais exigem absolutamente que todas as partições sejam amostradas na mesma taxa, para que, quando o mecanismo mesclar as páginas de estatísticas, ele possa ter certeza de que a distribuição amostrada é comparável.
REBUILD
necessariamente coleta dados a uma taxa de amostragem de 100%. Não há garantia de que a taxa de amostragem de 100% na partição 9 sempre seja a taxa de amostragem exata do restante das partições. Por esse motivo, parece que o mecanismo não pode mesclar as amostras e você acaba com um blob de estatísticas vazio. No entanto, o objeto de estatísticas ainda está lá:Você pode preencher o blob através de qualquer número de meios:
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;
ou
UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);
ou você pode aguardar a atualização do AutoStats na primeira compilação de um plano de consulta usando esse objeto:
Dito tudo isso, este post esclarecedor de Erin Stellato destaca o que passou a ser percebido como uma grande deficiência de estatísticas incrementais. Seus dados no nível da partição não são utilizados pelo otimizador na geração do plano de consulta, reduzindo o benefício presumido de estatísticas incrementais. Qual é o benefício atual das estatísticas incrementais? Eu diria que o utilitário principal deles é capaz de amostrar tabelas grandes de maneira mais consistente a uma taxa mais alta do que com as estatísticas tradicionais.
Usando seu exemplo, veja como as coisas ficam:
Uma atualização de estatísticas fullscan na estatística incremental custa 131 ms. Uma atualização de estatística fullscan na estatística não alinhada à partição custa 66 ms. A estatística não alinhada é mais lenta, provavelmente devido às despesas gerais resultantes da mesclagem das páginas de estatísticas individuais de volta ao histograma principal. No entanto, usando o objeto estatístico alinhado à partição, podemos atualizar uma partição e mesclá-la novamente no blob principal do histograma em 5 ms. Portanto, neste ponto, o administrador com a estatística incremental é confrontado com uma decisão. Eles podem diminuir o tempo geral de manutenção de estatísticas, apenas atualizando as partições que tradicionalmente precisariam ser atualizadas ou podem experimentar taxas de amostragem mais altas, de modo que possam obter mais linhas de amostra no mesmo período de tempo que o período de manutenção anterior. O primeiro permite espaço para respirar na janela de manutenção; o último pode enviar estatísticas em uma tabela muito grande para um local onde as consultas obtêm melhores planos com base em estatísticas mais precisas. Isso não é uma garantia e sua milhagem pode variar.
O leitor pode ver que 66 ms não é um momento doloroso de atualização estatística nesta tabela, então tentei configurar um teste no conjunto de dados stackexchange. Existem 6.418.608 postagens (excluindo as postagens do StackOverflow e todas as postagens de 2012 - um erro de dados da minha parte) no dump recente que baixei.
Particionei os dados
[CreationDate]
porque ... demo.Aqui estão alguns horários para alguns cenários bastante padrão (100% - reconstrução do índice, padrão - atualização automática de estatísticas ou
UPDATE STATISTICS
sem uma taxa de amostragem especificada:Digamos que somos mais sofisticados do que esses cenários padrão e decidimos que uma taxa de amostragem de 10% é a taxa mínima que deve fornecer os planos de que precisamos, mantendo o tempo de manutenção em um prazo razoável.
Até o momento, não há benefício claro em ter uma estatística incremental. No entanto, se alavancarmos a DMV não documentada
sys.dm_db_stats_properties_internal()
(abaixo), você poderá obter algumas dicas sobre quais partições você deseja atualizar. Digamos que fizemos alterações nos dados na partição 3 e queremos garantir que as estatísticas sejam novas para as consultas recebidas. Aqui estão as nossas opções:Aqui é onde precisamos tomar uma decisão. Tomamos a vitória de 63 ms. atualização de estatísticas baseada em partição ou aumentamos ainda mais a taxa de amostragem? Digamos que estamos dispostos a considerar o resultado inicial da amostragem em 50% em uma estatística incremental:
Podemos coletar muito mais dados, talvez configurando o otimizador para adivinhar melhor nossos dados (mesmo que ainda não esteja usando estatísticas no nível da partição) e podemos fazer isso mais rapidamente agora que temos estatísticas incrementais.
Uma última coisa divertida para descobrir, no entanto. E as atualizações de estatísticas síncronas? A taxa de amostragem de 50% é preservada mesmo quando os autostats entram em ação?
Excluí os dados da partição 3 e executei uma consulta no CreationDate e verifiquei e verifiquei as taxas com a mesma consulta abaixo. A taxa de amostragem de 50% foi preservada.
Então, para encurtar a história: Estatísticas Incrementais podem ser uma ferramenta útil com a quantidade certa de pensamento e trabalho de configuração inicial. No entanto, você deve conhecer o problema que está tentando resolver e, em seguida, precisa resolvê-lo adequadamente. Se você está recebendo estimativas de cardinalidade ruins, você pode ser capaz de obter melhores planos com uma taxa de amostragem estratégica e alguma intervenção investido. No entanto, você está obtendo apenas uma pequena parte do benefício, pois o histograma usado é a única página de estatísticas mesclada e não as informações no nível da partição. Se você sentir dor na janela de manutenção, talvez as estatísticas incrementais possam ajudá-lo, mas provavelmente exigirá que você configure um processo de intervenção de manutenção de alto nível. Independentemente disso, lembre-se de:
Espero que isto ajude
fonte