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 / 101956
Accepted
Dean MacGregor
Dean MacGregor
Asked: 2015-05-20 12:54:37 +0800 CST2015-05-20 12:54:37 +0800 CST 2015-05-20 12:54:37 +0800 CST

Otimize a visualização (e a tabela subjacente) para obter a média de carimbos de data/hora em horas

  • 772

Eu tenho esta tabela:

CREATE TABLE spp.rtprices (
  "interval" timestamp without time zone NOT NULL,
  rtlmp numeric(12,6),
  rtmcc numeric(12,6),
  rtmcl numeric(12,6),
  node_id integer NOT NULL,
  CONSTRAINT rtprices_pkey PRIMARY KEY ("interval", node_id),
  CONSTRAINT rtprices_node_id_fkey FOREIGN KEY (node_id)
      REFERENCES spp.nodes (node_id) MATCH SIMPLE
      ON UPDATE RESTRICT ON DELETE RESTRICT
)

E mais um índice relevante:

CREATE INDEX rtprices_node_id_interval_idx ON spp.rtprices (node_id, "interval");

Contra isso, fiz esta opinião:

  CREATE OR REPLACE VIEW spp.rtprices_hourly AS 
  SELECT (rtprices."interval" - '00:05:00'::interval)::date::timestamp without time zone AS pricedate,
  date_part('hour'::text, date_trunc('hour'::text, rtprices."interval" - '00:05:00'::interval))::integer + 1 AS hour,
  rtprices.node_id,
  round(avg(rtprices.rtlmp), 2) AS rtlmp,
  round(avg(rtprices.rtmcc), 2) AS rtmcc,
  round(avg(rtprices.rtmcl), 2) AS rtmcl
  FROM spp.rtprices
  GROUP BY date_part('hour'::text, date_trunc('hour'::text, rtprices."interval" - '00:05:00'::interval))::integer + 1,
           rtprices.node_id,
           (rtprices."interval" - '00:05:00'::interval)::date::timestamp without time zone;

O objetivo é fornecer médias das colunas numéricas para cada hora (os timestamps têm dados a cada 5 minutos). O problema é que uma consulta de um único dia para um único node_idleva mais de 30 segundos para 24 registros.

explain analyze select * from spp.rtprices_hourly
where node_id=20 and pricedate='2015-02-02'

Retorna isso :

   "HashAggregate  (cost=1128767.71..1128773.79 rows=135 width=28) (actual time=31155.023..31155.065 rows=24 loops=1)"
"  Group Key: ((date_part('hour'::text, date_trunc('hour'::text, (rtprices."interval" - '00:05:00'::interval))))::integer + 1), rtprices.node_id, (((rtprices."interval" - '00:05:00'::interval))::date)::timestamp without time zone"
"  ->  Bitmap Heap Scan on rtprices  (cost=10629.42..1128732.91 rows=2320 width=28) (actual time=25071.410..31153.715 rows=288 loops=1)"
"        Recheck Cond: (node_id = 20)"
"        Rows Removed by Index Recheck: 7142233"
"        Filter: (((("interval" - '00:05:00'::interval))::date)::timestamp without time zone = '2015-02-02 00:00:00'::timestamp without time zone)"
"        Rows Removed by Filter: 124909"
"        Heap Blocks: exact=43076 lossy=82085"
"        ->  Bitmap Index Scan on rtprices_node_id_interval_idx  (cost=0.00..10628.84 rows=464036 width=0) (actual time=68.999..68.999 rows=125197 loops=1)"
"              Index Cond: (node_id = 20)"
"Planning time: 5.243 ms"
"Execution time: 31155.392 ms"
postgresql index-tuning
  • 1 1 respostas
  • 97 Views

1 respostas

  • Voted
  1. Best Answer
    Erwin Brandstetter
    2015-05-20T16:52:57+08:002015-05-20T16:52:57+08:00

    Visualização mais simples

    Para este objetivo:

    O objetivo é fornecer médias das colunas numéricas para cada hora

    .. parece tão bom truncar para horas completas, que é mais simples e barato:

    CREATE OR REPLACE VIEW spp.rtprices_hourly AS 
    SELECT date_trunc('hour', "interval") AS hour
         , node_id
         , round(avg(rtlmp), 2) AS rtlmp
         , round(avg(rtmcc), 2) AS rtmcc
         , round(avg(rtmcl), 2) AS rtmcl
    FROM   spp.rtprices
    GROUP  BY 1, 2;
    

    consulta mais rápida

    De qualquer forma, uma consulta equivalente na exibição com predicados sargáveis ​​seria:

    SELECT *
    FROM   spp.rtprices_hourly
    WHERE  node_id = 20
    AND    hour >= '2015-02-02 0:0'::timestamp
    AND    hour <  '2015-02-03 0:0'::timestamp;
    

    Isso é mais rápido, mas ainda não tão rápido quanto poderia ser. O maior impacto no desempenho ocorre porque o índice só pode ser usado com uma condição de índice em node_id, que é preservada em seu estado original na exibição. É por isso que seu índice rtprices_node_id_interval_idxcom o node_idprimeiro é importante. Por quê?

    • Funcionamento de índices no PostgreSQL
    • Um índice composto também é bom para consultas no primeiro campo?

    O segundo predicado hourdeve ser filtrado depois que a tupla foi buscada no heap (a linha foi lida da tabela). A grande maioria das linhas é descartada no final do processo, muito trabalho para nada .

    Muito mais rápido com consulta direta

    Seria muito mais rápido executar a consulta original e aplicar predicados antes de agregar:

    SELECT date_trunc('hour', "interval") AS hour
         , node_id
         , round(avg(rtlmp), 2) AS rtlmp
         , round(avg(rtmcc), 2) AS rtmcc
         , round(avg(rtmcl), 2) AS rtmcl
    FROM   spp.rtprices
    WHERE  node_id = 20
    AND    "interval" >= '2015-02-02 0:0'::timestamp
    AND    "interval" <  '2015-02-03 0:0'::timestamp
    GROUP  BY 1, 2;
    

    Você verá as condições de índice para todos os predicados agora. O índice mais eficiente ainda é aquele com o node_idprimeiro. Por quê?

    • Índice e desempenho de várias colunas

    Rápido e curto: crie uma função

    Portanto, isso não funcionará bem com uma exibição. Em vez disso, use uma função:

    CREATE OR REPLACE FUNCTION rtprices_hourly(_node_id int
                                             , _from timestamp
                                             , _to timestamp = NULL)
      RETURNS TABLE (
        hour    timestamp
      , node_id int
      , rtlmp   numeric
      , rtmcc   numeric
      , rtmcl   numeric) AS
    $func$
    SELECT date_trunc('hour', r."interval")  -- AS hour
         , r.node_id
         , round(avg(r.rtlmp), 2)  -- AS rtlmp
         , round(avg(r.rtmcc), 2)  -- AS rtmcc
         , round(avg(r.rtmcl), 2)  -- AS rtmcl
    FROM   spp.rtprices r
    WHERE  r.node_id     = _node_id
    AND    r."interval" >= _from
    AND    r."interval" <  COALESCE(_to, _from + interval '1 day')
    GROUP  BY 1, 2
    $func$  LANGUAGE sql STABLE;
    
    • Tenha cuidado ao nomear conflitos entre parâmetros OUT e nomes de colunas. É por isso que qualifiquei todas as colunas aqui.

    Agora você obtém o melhor desempenho com uma consulta simples:

    SELECT * FROM rtprices_hourly(1, '2015-2-2 0:0'::timestamp, '2015-2-3 0:0'::timestamp);
    

    Eu coloquei um recurso de conveniência, o segundo parâmetro é padronizado como "um dia depois" se você omitir:

    SELECT * FROM rtprices_hourly(1, '2015-2-2 0:0'::timestamp);
    

    Mais sobre parâmetros de função e valores padrão:

    • Adicionar parâmetro de função à cláusula WHERE da consulta SQL

    Você pode consultar qualquer intervalo:

    SELECT * FROM rtprices_hourly(1, '2015-2-2 10:0'::timestamp, '2015-2-2 20:0'::timestamp);
    
    • 2

relate perguntas

  • Posso ativar o PITR depois que o banco de dados foi usado

  • Práticas recomendadas para executar a replicação atrasada do deslocamento de tempo

  • Os procedimentos armazenados impedem a injeção de SQL?

  • Sequências Biológicas do UniProt no PostgreSQL

  • Qual é a diferença entre a replicação do PostgreSQL 9.0 e o Slony-I?

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