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 / 258897
Accepted
Pedro Ludovico Bozzini
Pedro Ludovico Bozzini
Asked: 2020-02-05 11:17:29 +0800 CST2020-02-05 11:17:29 +0800 CST 2020-02-05 11:17:29 +0800 CST

SQL Server - Selecione o registro mais recente de cada grupo quando o desempenho for crítico

  • 772

Eu executo um banco de dados SQL Server 2016 onde tenho a seguinte tabela com mais de 100 milhões de linhas:

StationId | ParameterId |       DateTime       | Value
    1     |      2      | 2020-02-04 15:00:000 |  5.20
    1     |      2      | 2020-02-04 14:00:000 |  5.20
    1     |      2      | 2020-02-04 13:00:000 |  5.20
    1     |      3      | 2020-02-04 15:00:000 |  2.81
    1     |      3      | 2020-02-04 14:00:000 |  2.81
    1     |      4      | 2020-02-04 15:00:000 |  5.23
    2     |      2      | 2020-02-04 15:00:000 |  3.70
    2     |      4      | 2020-02-04 15:00:000 |  12.20
    3     |      2      | 2020-02-04 15:00:000 |  1.10

Esta tabela possui um índice clusterizado para StationId, ParameterId e DateTime, nesta ordem, todos crescentes.

O que eu preciso é, para cada par exclusivo StationId - ParameterId, retornar o valor mais recente da coluna DateTime:

StationId | ParameterId |       LastDate       
    1     |      2      | 2020-02-04 15:00:000 
    1     |      3      | 2020-02-04 15:00:000 
    1     |      4      | 2020-02-04 15:00:000 
    2     |      2      | 2020-02-04 15:00:000 
    2     |      4      | 2020-02-04 15:00:000 
    3     |      2      | 2020-02-04 15:00:000 

O que estou fazendo agora é a seguinte consulta, que leva cerca de 90 a 120 segundos para ser executada:

    SELECT StationId, ParameterId, MAX(DateTime) AS LastDate
    FROM  MyTable WITH (NOLOCK)
    GROUP BY StationId, ParameterId

Também vi muitos posts sugerindo o seguinte, que leva mais de 10 minutos para ser executado:

    SELECT StationId, ParameterId, DateTime AS LastDate
    FROM
    (
       SELECT StationId, ParameterId, DateTime
       ,ROW_NUMBER() OVER (PARTITION BY StationId,ParameterIdORDER BY DateTime DESC) as row_num
       FROM  MyTable WITH (NOLOCK)
    )
    WHERE row_num = 1

Mesmo no melhor caso (usando a cláusula GROUP BY e a função agregada MAX), o plano de execução não indica uma busca de índice:

Plano de execução da consulta

Detalhe da varredura de índice

Gostaria de saber se existe uma maneira melhor de realizar essa consulta (ou construir o índice) para obter um melhor tempo de execução.

sql-server index
  • 3 3 respostas
  • 40644 Views

3 respostas

  • Voted
  1. Best Answer
    David Browne - Microsoft
    2020-02-05T11:43:15+08:002020-02-05T11:43:15+08:00

    Se você tiver um número pequeno o suficiente de pares (StationID, ParameterID), tente uma consulta como esta:

    select StationID, ParameterID, m.DateTime LastDate 
    from StationParameter sp
    cross apply 
      (
         select top 1 DateTime 
         from MyTable 
         where StationID = sp.StationID
          and ParameterID = sp.ParameterID
         order by DateTime desc
      ) m
    

    Para habilitar o SQL Server para realizar uma pesquisa, buscando o mais recente DateTimepara cada par (StationID,ParameterID).

    Com apenas um índice clusterizado em (StationID, ParameterID, DateTime), não há como o SQL Server descobrir os pares distintos (StationID, ParameterID) sem verificar o nível folha do índice e pode encontrar o maior DateTime durante a verificação.

    Também com mais de 100 milhões de linhas, esta tabela pode ser melhor como um Clustered Columnstore em vez de um BTree Clustered Index.

    • 27
  2. Taczi
    2020-02-06T11:41:11+08:002020-02-06T11:41:11+08:00

    Se o desempenho é realmente crítico e você costuma perguntar à sua tabela a data mais recente... Por que não criar uma tabela de pesquisa de estação e parâmetro como chave com o carimbo de hora mais recente. Você precisa atualizar esta tabela toda vez que modificar a grande, mas desta forma você terá seus resultados quando precisar em milissegundos.

    • 0
  3. Connor
    2020-02-06T19:01:30+08:002020-02-06T19:01:30+08:00

    Com a abordagem CTE row_number, tente criar um índice não clusterizado em StationId, ParameterId, DateTime desc. Descobri que ter um índice com a ordem de classificação adequada que minha partição por cláusula de ordem usa melhorou o desempenho para mim.

    • 0

relate perguntas

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

  • Quanto "Padding" coloco em meus índices?

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

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

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