AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 111590
Accepted
JasonR
JasonR
Asked: 2015-08-20 09:45:18 +0800 CST2015-08-20 09:45:18 +0800 CST 2015-08-20 09:45:18 +0800 CST

As estatísticas desaparecem após a atualização incremental

  • 772

Temos um grande banco de dados SQL Server particionado 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 depois que o índice é reconstruído.

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!!!!!!'

Conforme mostrado, não podemos reconstruir índices por partição online sem perder todas as estatísticas para o índice. Este é um grande problema de manutenção para nós. Quase parece que a opção incremental de estatísticas precisa fazer parte da sintaxe de reconstrução de índice único ou a opção on-line precisa tratá-la adequadamente, como faz a opção off-line.

Por favor, deixe-me saber se eu estou perdendo alguma coisa?

Atualizações:

No que diz respeito à 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 back-load de dados), podemos simplesmente atualizar as estatísticas da partição e evitar rapidamente a criação de planos ruins para esse novo cliente. Acho que vou arquivá-lo com a Microsoft como um bug e ver o que eles têm a dizer e seguir com a solução de apenas reamostrar as estatísticas para essa partição.

Conectar relatório de bug:

As estatísticas desaparecem após a reconstrução do índice online com estatísticas incrementais

Atualização: a Microsoft confirmou que é um bug.

sql-server sql-server-2014
  • 1 1 respostas
  • 1473 Views

1 respostas

  • Voted
  1. Best Answer
    swasheck
    2015-08-20T10:44:15+08:002015-08-20T10:44:15+08:00

    Não tenho certeza se é um bug, por si só , mas é definitivamente uma ocorrência interessante. As reconstruções de partição online são novas no SQL Server 2014, portanto, pode haver alguns internos para resolver com isso.

    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. REBUILDnecessariamente amostra 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 será a taxa de amostragem exata do restante das partições. Por causa disso, 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á:

    select 
        check_time = sysdatetime(),                         
        schema_name = sh.name,
        table_name = t.name,
        stat_name = s.name,
        index_name = i.name,
        stats_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
        s.stats_id,
        s.has_filter,                       
        s.is_incremental,
        s.auto_created,
        sp.last_updated,    
        sp.rows,
        sp.rows_sampled,                        
        sp.unfiltered_rows,
        modification_counter 
    from sys.stats s 
    join sys.tables t 
        on s.object_id = t.object_id
    join sys.schemas sh
        on t.schema_id = sh.schema_id
    left join sys.indexes i 
        on s.object_id = i.object_id
        and s.name = i.name
    outer apply sys.dm_db_stats_properties(s.object_id, s.stats_id) sp
    where t.name = 'TransactionHistory' and sh.name = 'dbo'
    

    Você pode preencher o blob de várias maneiras:

    UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE;

    ou

    UPDATE STATISTICS dbo.TransactionHistory (IDX_ProductId) WITH RESAMPLE ON PARTITIONS (9);

    ou você pode esperar que o AutoStats seja atualizado na primeira compilação de um plano de consulta usando esse objeto:

    -- look at my creative query
    select * 
    from dbo.TransactionHistory
    where TransactionDate = '20140101';
    

    Tendo dito tudo isso, esta postagem esclarecedora de Erin Stellato destaca o que passou a ser percebido como uma grande deficiência de estatísticas incrementais. Seus dados em nível de partição não são usados ​​pelo otimizador na geração do plano de consulta, reduzindo o benefício presumido de estatísticas incrementais. Qual é, então, o benefício atual das estatísticas incrementais? Eu diria que sua principal utilidade é a capacidade de obter amostras de tabelas grandes de forma mais consistente a uma taxa mais alta do que com as estatísticas tradicionais.

    Usando seu exemplo, veja como as coisas ficam:

    set statistics time on;
    
    update statistics dbo.TransactionHistory(IDX_ProductId)
    with fullscan;
    
    --SQL Server Execution Times:
    --  CPU time = 94 ms,  elapsed time = 131 ms.
    
    
    update statistics dbo.TransactionHistory(IDX_ProductId)
    with resample on partitions(2);
    
     --SQL Server Execution Times:
     --  CPU time = 0 ms,  elapsed time = 5 ms.
    
    drop index IDX_ProductId On dbo.TransactionHistory;
    
    CREATE NONCLUSTERED INDEX IDX_ProductId ON dbo.TransactionHistory (ProductId) 
      WITH (DATA_COMPRESSION = ROW)  
      ON [PRIMARY]
    
    update statistics dbo.TransactionHistory(IDX_ProductId)
    with fullscan;
    
     --SQL Server Execution Times:
     --  CPU time = 76 ms,  elapsed time = 66 ms.
    

    Uma atualização de estatísticas de varredura completa na estatística incremental custa 131 ms. Uma atualização de estatísticas de varredura completa na estatística não alinhada por partição custa 66 ms. A estatística não alinhada é mais lenta provavelmente devido à sobrecarga incorrida com a fusão 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 do histograma principal em 5 ms. Portanto, neste ponto, o administrador com a estatística incremental se depara com uma decisão. Eles podem diminuir o tempo geral de manutenção de estatísticas atualizando apenas as partições que tradicionalmente precisam ser atualizadas ou podem experimentar taxas de amostragem mais altas, de modo que potencialmente obtenham mais linhas amostradas no mesmo período de tempo 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 planos melhores 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 tempo de atualização de estatísticas doloroso 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 despejo recente que baixei.

    Eu particionei os dados [CreationDate]porque ... demo.

    Aqui estão alguns tempos para alguns cenários bastante padrão (100% - reconstrução de índice, padrão - atualização automática de estatísticas ou UPDATE STATISTICSsem uma taxa de amostragem especificada:

    • Crie estatísticas não incrementais com Fullscan: tempo de CPU = 23500 ms, tempo decorrido = 22521 ms.
    • Criar estatística incremental com Fullscan: tempo de CPU = 20406 ms, tempo decorrido = 15413 ms.
    • Atualizar estatística não incremental com taxa de amostragem padrão: tempo de CPU = 406 ms, tempo decorrido = 408 ms.
    • Atualizar estatística incremental com taxa de amostragem padrão: tempo de CPU = 453 ms, tempo decorrido = 507 ms.

    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 nos fornecer os planos de que precisamos, mantendo o tempo de manutenção em um prazo razoável.

    • Atualize a estatística não incremental com amostra de 10 por cento: tempo de CPU = 2.344 ms, tempo decorrido = 2.441 ms.
    • Atualizar estatística incremental com amostra de 10 por cento: tempo de CPU = 2344 ms, tempo decorrido = 2388 ms.

    Até agora, não há nenhum benefício claro em ter uma estatística incremental. No entanto, se aproveitarmos o DMV não documentado sys.dm_db_stats_properties_internal() (abaixo), você poderá obter algumas informações sobre quais partições deseja atualizar. Digamos que fizemos alterações nos dados na partição 3 e queremos garantir que as estatísticas sejam atualizadas para as consultas recebidas. Aqui estão as nossas opções:

    • Atualização não incremental no padrão (também o comportamento padrão da atualização automática de estatísticas): 408 ms.
    • Atualização não incremental a 10%: 2441 ms.
    • Atualizar estatísticas incrementais, partição 3 com reamostragem (10% - nossa taxa de amostragem definida): tempo de CPU = 63 ms, tempo decorrido = 63 ms.

    Aqui é onde precisamos tomar uma decisão. Levamos 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 obter o impacto inicial da amostragem em 50% em uma estatística incremental:

    • Atualizar estatísticas incrementais em 50%: tempo decorrido = 16840 ms.
    • Atualizar estatísticas incrementais, partição 3 com reamostragem (50% - nosso novo tempo de atualização): tempo decorrido = 295 ms.

    Podemos obter amostras de muito mais dados, talvez configurando o otimizador para fazer melhores suposições sobre nossos dados (mesmo que ainda não esteja usando estatísticas em nível de 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 são ativados?

    Excluí os dados da partição 3 e executei uma consulta em CreationDate e verifiquei as taxas com a mesma consulta abaixo. A taxa de amostragem de 50% foi preservada.

    Então, resumindo: 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 então precisa resolvê-lo adequadamente. Se você estiver obtendo estimativas de cardinalidade ruins, poderá obter planos melhores com uma taxa de amostragem estratégica e alguma intervenção investida. No entanto, você está obtendo apenas uma pequena parte do benefício, pois o histograma usado é a página de estatísticas única e mesclada e não as informações no nível da partição. Se você está sentindo dor em sua 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. Sem considerar,:

    • Estatísticas criadas com índices que não são alinhados por partição com a tabela base.
    • Estatísticas criadas em bancos de dados secundários legíveis AlwaysOn.
    • Estatísticas criadas em bancos de dados somente leitura.
    • Estatísticas criadas em índices filtrados.
    • Estatísticas criadas em visualizações.
    • Estatísticas criadas em tabelas internas.
    • Estatísticas criadas com índices espaciais ou índices XML.

    Espero que isto ajude

    select 
        sysdatetime(),                          
        schema_name = sh.name,
        table_name = t.name,
        stat_name = s.name,
        index_name = i.name,
        leading_column = index_col(quotename(sh.name)+'.'+quotename(t.name),s.stats_id,1),
        s.stats_id,
        parition_number = isnull(sp.partition_number,1),
        s.has_filter,                       
        s.is_incremental,
        s.auto_created,
        sp.last_updated,    
        sp.rows,
        sp.rows_sampled,                        
        sp.unfiltered_rows,
        modification_counter = coalesce(sp.modification_counter, n1.modification_counter) 
    from sys.stats s 
    join sys.tables t 
        on s.object_id = t.object_id
    join sys.schemas sh
        on t.schema_id = sh.schema_id
    left join sys.indexes i 
        on s.object_id = i.object_id
            and s.name = i.name
    cross apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) sp
    outer apply sys.dm_db_stats_properties_internal(s.object_id, s.stats_id) n1
    where n1.node_id = 1
        and (
                (is_incremental = 0)
                   or
                (is_incremental = 1 and sp.partition_number is not null)
             )
        and t.name = 'Posts'
        and s.name like 'st_posts%'
    order by s.stats_id,isnull(sp.partition_number,1)
    
    • 18

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve