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 / 201660
Accepted
Steffen Mangold
Steffen Mangold
Asked: 2018-03-20 04:55:55 +0800 CST2018-03-20 04:55:55 +0800 CST 2018-03-20 04:55:55 +0800 CST

Otimize o índice em uma tabela de 2.135.044.521 linhas

  • 772

Eu tenho um problema de E/S com uma tabela grande.

Estatísticas gerais

A mesa tem as seguintes características principais:

  • ambiente: Banco de Dados SQL do Azure (camada é P4 Premium (500 DTUs))
  • linhas: 2.135.044.521
  • 1.275 partições usadas
  • índice clusterizado e particionado

Modelo

Esta é a implementação da tabela:

CREATE TABLE [data].[DemoUnitData](
    [UnitID] [bigint] NOT NULL,
    [Timestamp] [datetime] NOT NULL,
    [Value1] [decimal](18, 2) NULL,
    [Value2] [decimal](18, 2) NULL,
    [Value3] [decimal](18, 2) NULL,
    CONSTRAINT [PK_DemoUnitData] PRIMARY KEY CLUSTERED 
    (
        [UnitID] ASC,
        [Timestamp] ASC
    )
)
GO

ALTER TABLE [data].[DemoUnitData] WITH NOCHECK ADD CONSTRAINT [FK_DemoUnitData_Unit] FOREIGN KEY([UnitID])
REFERENCES [model].[Unit] ([ID])
GO

ALTER TABLE [data].[DemoUnitData] CHECK CONSTRAINT [FK_DemoUnitData_Unit]
GO

O particionamento está relacionado a isso:

CREATE PARTITION SCHEME [DailyPartitionSchema] AS PARTITION [DailyPartitionFunction] ALL TO ([PRIMARY])

CREATE PARTITION FUNCTION [DailyPartitionFunction] (datetime) AS RANGE RIGHT
FOR VALUES (N'2017-07-25T00:00:00.000', N'2017-07-26T00:00:00.000', N'2017-07-27T00:00:00.000', ... )

Qualidade de serviço

Eu acho que os índices e estatísticas são bem mantidos todas as noites por reconstrução/reorganização/atualização incremental.

Estas são as estatísticas de índice atuais das partições de índice mais usadas:

Estatísticas da partição

Estas são as propriedades estatísticas atuais das partições mais usadas:

Estatisticas

Problema

Eu executo uma consulta simples em alta frequência na tabela.

SELECT [UnitID]
    ,[Timestamp]
    ,[Value1]
    ,[Value2]
    ,[Value3]
FROM [data].[DemoUnitData]
WHERE [UnitID] = 8877 AND [Timestamp] >= '2018-03-01' AND [Timestamp] < '2018-03-13'
OPTION (MAXDOP 1)

contagem excecional

O plano de execução fica assim: https://www.brentozar.com/pastetheplan/?id=rJvI_4TtG

Meu problema é que essas consultas produzem uma quantidade extremamente alta de operações de E/S, resultando em um gargalo de PAGEIOLATCH_SHesperas.

melhores esperas

Pergunta

Eu li que PAGEIOLATCH_SHas esperas geralmente estão relacionadas a índices não bem otimizados. Você tem alguma recomendação para mim sobre como reduzir as operações de E/S? Talvez adicionando um índice melhor?


Resposta 1 - relacionada ao comentário de @S4V1N

O plano de consulta postado foi de uma consulta que executei no SSMS. Após seu comentário, faço uma pesquisa sobre o histórico do servidor. A consulta real executada do serviço parece um pouco diferente (relacionada ao EntityFramework).

(@p__linq__0 bigint,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7)) 

SELECT 1 AS [C1], [Extent1] 
   .[Timestamp] AS [Timestamp], [Extent1] 
   .[Value1] AS [Value1], [Extent1] 
   .[Value2] AS [Value2], [Extent1] 
   .[Value3] AS [Value3]  
FROM [data].[DemoUnitData] AS [Extent1]  
WHERE ([Extent1].[UnitID] = @p__linq__0)  
AND ([Extent1].[Timestamp] >= @p__linq__1)  
AND ([Extent1].[Timestamp] < @p__linq__2) OPTION (MAXDOP 1) 

Além disso, o plano parece diferente:

https://www.brentozar.com/pastetheplan/?id=H1fhALpKG

ou

https://www.brentozar.com/pastetheplan/?id=S1DFQvpKz

E como você pode ver aqui, nosso desempenho de banco de dados dificilmente é influenciado por essa consulta.

SQL principal

Resposta 2 - relacionada à resposta de @Joe Obbish

Para testar a solução, substituí o Entity Framework por um SqlCommand simples. O resultado foi um incrível aumento de desempenho!

O plano de consulta agora é o mesmo do SSMS e as leituras e gravações lógicas caem para ~8 por execução.

A carga geral de E/S cai para quase 0! Queda de E/S

Também explica por que recebo uma grande queda de desempenho depois de alterar o intervalo de partição de mensal para diário. A falta de eliminação de partição resultou em mais partições para verificar.

sql-server performance
  • 1 1 respostas
  • 302 Views

1 respostas

  • Voted
  1. Best Answer
    Joe Obbish
    2018-03-20T10:00:30+08:002018-03-20T10:00:30+08:00

    Você poderá reduzir as PAGEIOLATCH_SHesperas por essa consulta se conseguir alterar os tipos de dados gerados pelo ORM. A Timestampcoluna em sua tabela tem um tipo de dados de DATETIMEmas os parâmetros @p__linq__1e @p__linq__2tem tipos de dados de DATETIME2(7). Essa diferença é o motivo pelo qual o plano de consulta para as consultas ORM é muito mais complicado do que o primeiro plano de consulta que você postou que tinha filtros de pesquisa codificados. Você pode obter uma dica disso no XML também:

    <ScalarOperator ScalarString="GetRangeWithMismatchedTypes([@p__linq__1],NULL,(22))">
    

    Como está, com a consulta ORM você não pode obter nenhuma eliminação de partição. Você obterá pelo menos algumas leituras lógicas para cada partição definida na função de partição, mesmo se estiver apenas procurando por um dia de dados. Dentro de cada partição, você obtém uma busca de índice para que não demore muito para o SQL Server passar para a próxima partição, mas talvez todo esse IO esteja somando.

    Fiz uma reprodução simples para ter certeza. Existem 11 partições definidas na função de partição. Para esta consulta:

    DECLARE @p__linq__0 bigint = 2000;
    DECLARE @p__linq__1 datetime2(7) = '20180103';
    DECLARE @p__linq__2 datetime2(7) = '20180104';
    
    SELECT 1 AS [C1]
    , [Extent1].[Timestamp] AS [Timestamp]
    , [Extent1].[Value1] AS [Value1]
    FROM [DemoUnitData] AS [Extent1]  
    WHERE ([Extent1].[UnitID] = @p__linq__0)  
    AND ([Extent1].[Timestamp] >= @p__linq__1)  
    AND ([Extent1].[Timestamp] < @p__linq__2)
    OPTION (MAXDOP 1) ;
    

    Veja como é o IO:

    Tabela 'DemoUnitData'. Contagem de varredura 11, leituras lógicas 40

    Quando eu corrijo os tipos de dados:

    DECLARE @p__linq__0 bigint = 2000;
    DECLARE @p__linq__1 datetime = '20180103';
    DECLARE @p__linq__2 datetime = '20180104';
    
    SELECT 1 AS [C1]
    , [Extent1].[Timestamp] AS [Timestamp]
    , [Extent1].[Value1] AS [Value1]
    FROM [DemoUnitData] AS [Extent1]  
    WHERE ([Extent1].[UnitID] = @p__linq__0)  
    AND ([Extent1].[Timestamp] >= @p__linq__1)  
    AND ([Extent1].[Timestamp] < @p__linq__2)
    OPTION (MAXDOP 1) ;
    

    O IO é reduzido como resultado da eliminação da partição:

    Tabela 'DemoUnitData'. Contagem de varredura 2, leituras lógicas 8

    • 7

relate perguntas

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

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

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

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