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 / 302234
Accepted
ConanTheGerbil
ConanTheGerbil
Asked: 2021-11-07 07:17:17 +0800 CST2021-11-07 07:17:17 +0800 CST 2021-11-07 07:17:17 +0800 CST

Tempo de execução diferente para a mesma consulta em diferentes bancos de dados Postgres

  • 772

Eu tenho dois bancos de dados idênticos, desenvolvimento e ao vivo.

Eu executo esta consulta em ambos ....

select count(*) FROM DeviceB where deviceID not in (SELECT distinct deviceId FROM Device)

Na dev box a consulta demora cerca de 100ms, na live demora cerca de uma hora.

Ambas as tabelas têm um campo de chave primária chamado deviceId, ambos os bancos de dados têm estrutura idêntica e ambos têm dados muito semelhantes (nenhuma das tabelas contém mais de um milhão de linhas). Ambos os bancos de dados são limpos/analisados ​​regularmente, ambos foram feitos nas últimas 12 horas.

Cada banco de dados está em um computador diferente, o hardware é diferente para cada um, mas em 99% do tempo o live box é cerca de 10% mais lento.

Tanto quanto eu posso dizer, ambos os bancos de dados são configurados da mesma forma.

Meu palpite é que há alguma diferença sutil na distribuição dos dados em cada banco de dados que afeta a escolha do plano de explicação.

Minhas perguntas são:

  • Existe alguma maneira de forçar o banco de dados a usar um índice específico?
  • Existe uma forma diferente de consulta SQL que produziria os mesmos resultados, mas mais rapidamente?

explicar plano dev - leva menos de um segundo:

Aggregate  (cost=7806.68..7806.69 rows=1 width=8)
  ->  Seq Scan on deviceb  (cost=4624.86..7702.06 rows=41848 width=0)
        Filter: (NOT (hashed SubPlan 1))
        SubPlan 1
          ->  Unique  (cost=0.29..4404.59 rows=88108 width=7)
                ->  Index Only Scan using device_pkey on device  (cost=0.29..4184.32 rows=88108 width=7)

explicar o plano ao vivo - leva cerca de uma hora:

Finalize Aggregate  (cost=747368287.67..747368287.68 rows=1 width=8)
  ->  Gather  (cost=747368287.46..747368287.67 rows=2 width=8)
        Workers Planned: 2
        ->  Partial Aggregate  (cost=747367287.46..747367287.47 rows=1 width=8)
              ->  Parallel Seq Scan on deviceb  (cost=0.42..747367217.98 rows=27789 width=0)
                    Filter: (NOT (SubPlan 1))
                    SubPlan 1
                      ->  Materialize  (cost=0.42..26001.96 rows=156913 width=7)
                            ->  Unique  (cost=0.42..22822.40 rows=156913 width=7)
                                  ->  Index Only Scan using device_pkey on device  (cost=0.42..21930.12 rows=156913 width=7)

Eu comparei as versões dev/live das tabelas usando pgAdmin4 - simplesmente destacando o objeto e selecionando as propriedades de cada tabela e seus índices e restrições.

Além disso - meus testes (em ambos os bancos de dados) foram feitos sem outros usuários conectados.

DDL, conforme solicitado:

CREATE TABLE public.device (
    deviceid character(6) COLLATE pg_catalog."default" NOT NULL,
    recentfixtime timestamp without time zone,
    newfixes integer DEFAULT 0,
    lastfixid bigint DEFAULT 0,
    CONSTRAINT device_pkey PRIMARY KEY (deviceid)
        USING INDEX TABLESPACE fastspace
);


CREATE TABLE public.deviceb  (
    deviceid character(6) COLLATE pg_catalog."default" NOT NULL,
    flightid integer DEFAULT 0,
    lastfirstfixtime timestamp without time zone,
    lastprocfixtime timestamp without time zone,
    lastprocfly boolean,
    priority integer DEFAULT 0,
    lastlandtime timestamp without time zone,
    CONSTRAINT deviceb_pkey PRIMARY KEY (deviceid)
        USING INDEX TABLESPACE fastspace
)

ATUALIZAÇÃO - RESOLVIDO, graças a Jjanes, a versão sugerida é incrivelmente rápida em ambos os bancos de dados.

select count(*) FROM DeviceB where NOT EXISTS (
    SELECT 1 from Device where Device.deviceID=DeviceB.deviceID
)

Admito que ainda não tenho certeza de qual é a causa raiz, mas, para ser completo, tentarei responder a algumas das outras perguntas. O Autoanalyse ainda está ativado (pgAdmin/statistics mostra uma última data do Autoanalyse no início desta manhã. ambas as tabelas (ao vivo) têm menos de 200.000 linhas, ambas as tabelas no dev têm menos de 100.000. O hardware nas caixas dev/live é diferente (o maior diferença é que dev tem 32G de memória, live apenas 16G. Possivelmente a diferença mais significativa está nas versões, dev é 13.1, live ainda está em 10.4

postgresql performance
  • 2 2 respostas
  • 548 Views

2 respostas

  • Voted
  1. Best Answer
    jjanes
    2021-11-07T18:29:04+08:002021-11-07T18:29:04+08:00

    Fiz uma série de perguntas investigando a causa raiz. Mas, independentemente dos detalhes exatos da causa raiz, você pode se isolar do problema usando NOT EXISTS em vez de NOT IN.

    select count(*) FROM DeviceB where NOT EXISTS (
        SELECT 1 from Device where Device.deviceID=DeviceB.deviceID
    )
    
    • 1
  2. Erwin Brandstetter
    2021-11-07T15:27:03+08:002021-11-07T15:27:03+08:00

    Existe alguma maneira de forçar o banco de dados a usar um índice específico?

    Não. Não diretamente. Você pode "desabilitar" outros métodos de acesso para fazer o Postgres escolher uma varredura de índice ou varredura de índice de bitmap. Ver:

    • Criando índice de várias colunas para WHERE e ORDER BY

    Mas você não pode instruí-lo diretamente a usar um determinado índice. Esse não é o problema aqui de qualquer maneira.

    Existe uma forma diferente de consulta SQL que produziria os mesmos resultados, mas mais rapidamente?

    Sim. Soltar DISTINCT:

    SELECT count(*) FROM deviceb
    WHERE deviceid NOT IN (SELECT deviceid FROM device);
    

    Tentar remover duplicatas de grandes conjuntos é caro. Como device.deviceidé o PRIMARY KEY, não pode haver duplicatas.

    Se valores NULL ou duplicatas pudessem estar envolvidos, examinaríamos outros estilos de consulta, mas para duas chaves primárias, a consulta deve ser a ideal.

    A varredura sequencial paralela devicebé o problema, como vemos aqui:

    Verificação sequencial paralela no dispositivob (custo=0,42.. 747367217,98 linhas=27789 largura=0)

    Nenhum índice envolvido. Isso não deve ser tão caro. Também me pergunto por que não vemos uma linha como:

    'Linhas removidas pelo filtro: 123456'

    Que versão do Postgres é essa? E como você produziu exatamente o plano de consulta?

    Ou algo está errado com a tabela :

    • Muito mais linhas do que você pensa? Verificar com:
    SELECT count(*) FROM deviceb;
    
    • Tabela extrema e inchaço do índice? Verificar com:
    SELECT pg_size_pretty(pg_table_size('deviceb'))
         , pg_size_pretty(pg_table_size('deviceb_pkey'));
    
    SELECT * FROM pg_stat_user_tables WHERE relname = 'deviceb';
    

    Corrija com outro VACUUM ANALYZE deviceb;, talvez até VACUUM FULL ANALYZE deviceb;porque não há outros usuários conectados de qualquer maneira (?)

    • Fechaduras exclusivas?

    Não pode ser isso. Você disse:

    nenhum outro usuário conectado.

    • Problemas de hardware?

    Ou algo está errado com o paralelismo . Tente desativá-lo (para depuração!) e teste novamente:

    SET max_parallel_workers_per_gather = 0;
    

    Também:

    Ambos os bancos de dados são limpos/analisados ​​regularmente, ambos foram feitos nas últimas 12 horas.

    Parece que você está executando o manual VACUUM/ ANALYZE. Você desativou autovacuum? (Normalmente, você não deveria.)

    Embora a varredura sequencial dolorosamente lenta (paralela) deva ser examinada, eu me pergunto por que não vemos uma varredura somente de índice divicebpara começar. Com mesas recém VACUUM'ed e um TABLESPACEnome fastspaceque eu esperaria tanto. Você está ciente de que alguns parâmetros-chave podem ser definidos porTABLESPACE ? O mais importante seq_page_coste random_page_cost. Curti:

    ALTER TABLESPACE fastspace SET (seq_page_cost = 0.5, random_page_cost = 1);
    

    Ajuste às características do seu "fastspace".

    • 0

relate perguntas

  • Sequências Biológicas do UniProt no PostgreSQL

  • 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?

  • 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