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 / 332186
Accepted
laurent
laurent
Asked: 2023-10-17 02:16:35 +0800 CST2023-10-17 02:16:35 +0800 CST 2023-10-17 02:16:35 +0800 CST

Por que essa consulta do Postgres é tão lenta?

  • 772

Estou tentando depurar a consulta lenta abaixo, mas estou lutando para entender por que ela é lenta. Posso ver que tanto o plano quanto o subplano fazem uma varredura de índice, incluindo uma "varredura somente de índice" para o subplano, portanto ambos devem ser rápidos. No entanto, esta consulta específica leva 7 segundos.

Alguma ideia desta saída EXPLAIN onde pode estar o problema?

select "id", "item_id", "item_name", "type", "updated_time" from "changes"
where (
  ((type = 1 OR type = 3) AND user_id = 'USER_ID')
  or type = 2 AND item_id IN (SELECT item_id FROM user_items WHERE user_id = 'USER_ID')
) and "counter" > '35885954' order by "counter" asc limit 100;
 Limit  (cost=8409.70..8553.44 rows=100 width=101) (actual time=7514.730..7514.731 rows=0 loops=1)
   ->  Index Scan using changes_pkey on changes  (cost=8409.70..2387708.44 rows=1655325 width=101) (actual time=7514.728..7514.729 rows=0 loops=1)
         Index Cond: (counter > 35885954)
         Filter: ((((type = 1) OR (type = 3)) AND ((user_id)::text = 'USER_ID'::text)) OR ((type = 2) AND (hashed SubPlan 1)))
         Rows Removed by Filter: 11378536
         SubPlan 1
           ->  Index Only Scan using user_items_user_id_item_id_unique on user_items  (cost=0.56..8401.57 rows=3030 width=24) (actual time=0.085..3.011 rows=3589 loops=1)
                 Index Cond: (user_id = 'USER_ID'::text)
                 Heap Fetches: 2053
 Planning Time: 0.245 ms
 Execution Time: 7514.781 ms
(11 rows)
postgresql
  • 2 2 respostas
  • 56 Views

2 respostas

  • Voted
  1. jjanes
    2023-10-17T03:53:21+08:002023-10-17T03:53:21+08:00

    Ler 11.378.536 linhas não é magicamente rápido só porque você faz isso com um índice. E é aí que está o problema, ele tem que ler esse número de linhas.

    Não sabemos quais partes dessa complexa condição de filtro levam à falha da maioria das linhas, o que torna difícil propor otimizações com confiança. Talvez um índice (type, counter)ou (type, user_id)ajude. Ou você pode dividir a consulta em duas partes na condição OR e combiná-las com UNION.

    • 4
  2. Best Answer
    Erwin Brandstetter
    2023-10-18T14:41:54+08:002023-10-18T14:41:54+08:00

    Divida a consulta ao longo do arquivo OR. As duas consultas resultantes são mutuamente exclusivas, então combine-as com UNION ALL:

    (
    SELECT id, item_id, item_name, type, updated_time
    FROM   changes
    WHERE  counter > '35885954'
    AND    TYPE IN (1, 3)
    AND    user_id = 'USER_ID'
    ORDER  BY counter
    LIMIT  100
    )
    UNION  ALL
    SELECT id, item_id, item_name, type, updated_time
    FROM   changes
    WHERE  counter > '35885954'
    AND    TYPE = 2
    AND    item_id IN (SELECT item_id FROM user_items WHERE user_id = 'USER_ID')
    ORDER  BY counter
    LIMIT  100;
    

    Apoie o primeiro SELECTcom este índice parcial de múltiplas colunas para torná-lo extremamente rápido:

    CREATE INDEX ON changes (user_id, counter) WHERE type IN (1, 3);
    

    Ver:

    • Índice e desempenho de várias colunas

    A segunda SELECTé menos clara. Um índice com liderança counterdeve servir melhor enquanto LIMITfor pequeno e a participação item_iddo dado user_idnão for muito pequena.

    CREATE INDEX ON changes (counter, item_id) WHERE type = 2;
    

    Caso contrário, mudar as colunas de índice para (item_id, counter)pode ser melhor.

    Coloquei um separado LIMIT 100para o primeiro SELECT, que é logicamente redundante, mas pode produzir um plano de consulta melhor. O segundo LIMIT 100se aplica a toda a consulta. Pode até ajudar anexar um separado LIMIT 100ao segundo SELECTtambém (com um conjunto extra de parênteses). Não tenho certeza. Teste e relate o que funcionou melhor.

    • 1

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