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 / 342744
Accepted
Justin Lowen
Justin Lowen
Asked: 2024-10-02 23:51:11 +0800 CST2024-10-02 23:51:11 +0800 CST 2024-10-02 23:51:11 +0800 CST

PostgreSQL - Estimativas de linha que levam a loops aninhados sendo selecionados com muita frequência, como melhorar as estimativas de linha

  • 772

Estou executando o PG10 (em breve para mudar para o PG13) e estou tendo problemas de desempenho com uma consulta específica. Também testei no PG13 e obtive resultados semelhantes. A maioria das junções nesta consulta maior são selecionadas para Nested Joins, mas parece que um Hash Join seria mais apropriado para a maioria.

Vejo que os primeiros nós unidos podem estar direcionando as estatísticas de junções posteriores, onde as estimativas de linha são bem baixas. As primeiras junções são as seguintes: https://explain.dalibo.com/plan/b5045eb7cffdf0dhDalibo Explica Visualização

SELECT * from workflowable_resource where sample_type_id in (SELECT resource_id from resource where name = 'Test Order')

Embora essa consulta menor seja bem rápida, vejo muitos exemplos em que Nested Loop é selecionado incorretamente, onde um Hash Join pode ter um desempenho melhor. (A estimativa de linha é 1, ou próximo de 1, mas as linhas reais são ordens de magnitude maiores)

Quais são algumas técnicas gerais para melhorar estimativas de linha nesses casos? Tentei aumentar default_statistics_target para 10000 e analisar todas as tabelas novamente, mas não vi nenhuma melhoria nas estimativas de linha.

Na consulta maior, no banco de dados ampliado, há um nó tomando todo o tempo. Índice de varredura de loop aninhado Há uma varredura de índice na tabela, mas ela é realizada em um loop aninhado, pois o lado esquerdo é estimado em 1 linha, mas neste ponto está sendo executado com 178.000 linhas. Parece que erros de estimativas de linhas anteriores estão sendo levados adiante.

postgresql
  • 2 2 respostas
  • 57 Views

2 respostas

  • Voted
  1. Best Answer
    jjanes
    2024-10-03T01:49:05+08:002024-10-03T01:49:05+08:00

    Para a primeira consulta, ele não sabe qual resource_id específico está associado ao nome de 'Test Order' até que o planejamento termine. Então, ele não pode usar esse valor específico para estimar o número de linhas de workflowable_resource que ele encontrará. Então, em vez disso, ele tem que usar a estimativa genérica, que basicamente será #number of rows in workflowable_resource / n_distinct for sample_type_id. Não há muito que você possa fazer sobre isso com essa consulta, nenhuma quantidade de estatísticas adicionais vai ajudar você, pois a estimativa é genérica de qualquer maneira (a menos que n_distinct esteja muito errado). Você pode dividi-la em duas consultas, conectando a saída de uma no parâmetro da outra. Mas você tem que fazer isso manualmente, não há como instruir o PostgreSQL a executar a consulta interna e então replanejar a externa com base nos resultados. Além disso, provavelmente não importa, pois não vejo razão para pensar que uma estimativa melhor resultaria em um plano melhor.

    Para a consulta maior, talvez uma estimativa melhor levaria a um plano melhor, mas as informações fornecidas são inadequadas para especular. Não temos nem o plano real nem a consulta real.

    • 1
  2. jjanes
    2024-10-05T04:14:32+08:002024-10-05T04:14:32+08:00

    O problema com sua consulta muito maior é bem diferente do que com a primeira, então estou adicionando uma segunda resposta para discutir esta.

    O primeiro lugar onde a seletividade está muito errada é aqui:

    ->  Hash Join  (cost=542.37..2099.91 rows=1 width=12) (actual time=0.340..20.327 rows=6576 loops=1)                                                                                                         
      ->  Seq Scan on three_echo kilo_five  (cost=0.00..1406.89 rows=57389 width=8) (actual time=0.020..8.036 rows=57395 loops=1)
      ->  Hash  (cost=540.67..540.67 rows=136 width=4) (actual time=0.111..0.121 rows=3 loops=1)
    

    Então ele pensa que das 60.000 linhas da varredura seq, apenas uma corresponderá a qualquer linha da tabela hash. Mas, em vez disso, 1/10 delas encontra um parceiro na tabela hash. Mesmo que a tabela hash seja 40 vezes menor do que ele pensa que será. Então, eu estou supondo que o filtro aplicado ao construir a tabela hash seletivamente extrai linhas que têm valores que são muito comuns na tabela seq-scanned (então esta parte na verdade é bastante semelhante ao problema na primeira consulta). Talvez você pudesse escrever uma consulta muito mais simples que incorporasse esta junção hash e nada mais, veja se o problema de seletividade ainda existe e, em seguida, explore as entradas pg_stats para as colunas relevantes das tabelas relevantes. Talvez você pudesse compartilhar a versão não ofuscada dessa consulta mais focada, pois a ofuscação realmente torna difícil raciocinar sobre o que está acontecendo.

    No entanto, não tenho certeza se esse problema de estimativa de linha é realmente o principal culpado pelo desempenho lento.

    Se olharmos para a linha que realmente leva todo o tempo:

    -> Index Scan using oscar_mike on echo_four kilo_golf (cost=0.42..1,427.16 rows=11 width=12) (actual time=2.775..3.445 rows=4 loops=178,773)
       Index Cond: (kilo_golf.delta_two = alpha_xray_charlie2.four_kilo)
       Buffers: shared hit=93,849,709 dirtied=1
    

    Este índice retorna 4*178773 linhas. Por que são necessários 93849709/4/178773 = 131 acessos de buffer para cada linha retornada? Isso é como 60 vezes mais acessos de buffer do que o que parece razoável para mim. Acho que o índice está cheio de tuplas mortas que ainda não foram removidas, ou talvez esteja terrivelmente fragmentado ou algo assim. Eu faria o VACUUM VERBOSE manualmente nesta tabela e veria se isso corrigia (ou melhorava substancialmente) o problema. Se não, eu REINDEXARIA este índice específico e veria se isso resolveu. Se nenhum deles funcionar, compartilhe conosco a saída do VACUUM VERBOSE.

    • 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