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 / 327944
Accepted
Hasan Can Saral
Hasan Can Saral
Asked: 2023-06-06 17:04:16 +0800 CST2023-06-06 17:04:16 +0800 CST 2023-06-06 17:04:16 +0800 CST

JOIN com uma tabela pequena faz com que o plano de execução mude e a consulta fique drasticamente lenta

  • 772

Eu tenho as seguintes tabelas:

CREATE TABLE acl_sid (
 id bigserial not null primary key,
 principal boolean not null,
 sid varchar(100) not null,
 constraint unique_uk_1 unique(sid,principal) );

CREATE TABLE users(
 id NUMERIC(20, 0) NOT NULL DEFAULT NEXTVAL('users_sequence') PRIMARY KEY,
 email VARCHAR(255) NOT NULL,
    -- some ~10 columns omitted
 );

CREATE TABLE authorities (
 user_id NUMERIC(20, 0) NOT NULL,
 sid_id  BIGINT         NOT NULL,
 CONSTRAINT fk_authorities_users FOREIGN KEY (user_id) REFERENCES users (id) ON UPDATE CASCADE ON DELETE CASCADE,
 CONSTRAINT fk_authorities_sids FOREIGN KEY (sid_id) REFERENCES acl_sid (id) ON UPDATE CASCADE ON DELETE CASCADE );


CREATE SEQUENCE decidables_sequence START WITH 1 NO MAXVALUE;


CREATE TABLE decidables (
 id NUMERIC(20, 0) NOT NULL DEFAULT NEXTVAL('decidables_sequence') PRIMARY KEY,
 assigned_to NUMERIC(20, 0) DEFAULT NULL NULL,
 CONSTRAINT fk_decidables_assigned_to FOREIGN KEY (assigned_to) REFERENCES users (id) ON UPDATE CASCADE ON DELETE SET NULL );

CREATE TABLE decidables_transactions (
 decidable_id NUMERIC(20, 0) NOT NULL PRIMARY KEY,
 transaction_date TIMESTAMP DEFAULT NULL NULL,
 transaction_id VARCHAR(255) DEFAULT NULL,
 -- some 100 columns here
 CONSTRAINT uq_decidables_transactions_transaction_id UNIQUE (transaction_id),
 CONSTRAINT fk_decidables_transactions_decidable_id FOREIGN KEY (decidable_id) REFERENCES decidables (id) ON UPDATE CASCADE ON DELETE CASCADE );

CREATE TABLE decidables_transactions_mv (
 decidable_id NUMERIC(20, 0) NOT NULL,
 transaction_date TIMESTAMP DEFAULT NULL NULL,
 -- some 10 columns here, excerpt from decidables_transactions
 assigned_to NUMERIC(20, 0) DEFAULT NULL NULL,
 CONSTRAINT fk_decidables_transactions_mv_decidable_id_idx FOREIGN KEY (decidable_id) REFERENCES decidables (id) ON UPDATE CASCADE ON DELETE CASCADE,
 CONSTRAINT fk_decidables_transactions_mv_assigned_to_idx FOREIGN KEY (assigned_to) REFERENCES users (id) ON UPDATE CASCADE ON DELETE SET NULL );

CREATE INDEX decidable_id_mv_idx ON decidables_transactions_mv (decidable_id);
-- few more indexes on omitted columns, that are not being used in the following queries
CREATE INDEX transaction_date_mv_idx ON decidables_transactions_mv (transaction_date, decidable_id);

Eu tenho esta consulta de paginação de conjunto de chaves que funciona muito bem:

SELECT d.*,
       t.*,
       u.id    AS ass_to_id,
       u.email AS ass_to_email,
       NULL    AS ass_to_authority
FROM decidables d
         JOIN decidables_transactions t ON d.id = t.decidable_id
         LEFT JOIN users u ON d.assigned_to = u.id AND u.deleted_at IS NULL
         -- some more joins omitted for simplicity
         JOIN (SELECT t.decidable_id, t.transaction_date
               FROM decidables_transactions_mv t
               ORDER BY t.transaction_date DESC, t.decidable_id DESC
               LIMIT 10) AS decidables_table ON d.id = decidables_table.decidable_id
ORDER BY t.transaction_date DESC, t.decidable_id DESC;

Mas quando tento selecionar a autoridade do usuário:

SELECT d.*,
       t.*,
       u.id  AS ass_to_id,
       u.email AS ass_to_email,
       s.sid AS ass_to_authority
FROM decidables d
         JOIN decidables_transactions t ON d.id = t.decidable_id
         LEFT JOIN users u ON d.assigned_to = u.id AND u.deleted_at IS NULL
         LEFT JOIN authorities a ON a.user_id = u.id
         LEFT JOIN acl_sid s ON a.sid_id = s.id
         -- some more joins omitted for simplicity
         JOIN (SELECT t.decidable_id, t.transaction_date
               FROM decidables_transactions_mv t
               ORDER BY t.transaction_date DESC, t.decidable_id DESC
               LIMIT 10) AS decidables_table ON d.id = decidables_table.decidable_id
ORDER BY t.transaction_date DESC, t.decidable_id DESC;

Começa a demorar alguns minutos. Eu tenho cerca de 10 linhas em ~ 10 userslinhas acl_side ~ 2 milhões em e decidables.decidables_transactionsdecidables_transactions_mv

Os planos de execução são os seguintes:

  • Consulta rápida
  • Consulta lenta

Por que a consulta tem um desempenho muito diferente e fica drasticamente lenta?

postgresql
  • 1 1 respostas
  • 39 Views

1 respostas

  • Voted
  1. Best Answer
    Andrea B.
    2023-06-08T21:21:57+08:002023-06-08T21:21:57+08:00

    LIMIT 10É a chave.

    Na consulta rápida, o mecanismo começa calculando a decidables_tablesubconsulta com LIMIT 10, que retorna apenas 10 id decidíveis. Em seguida, ele une todas as outras tabelas a essas 10 linhas, o que é obviamente rápido.

    Quando você adiciona outras tabelas LEFT JOINed na consulta lenta, o mecanismo aparentemente não vê essa oportunidade e começa juntando a decidablestabela (com todos os seus milhões de linhas) com as outras tabelas. Como esses são LEFT JOINS, mesmo que você tenha apenas 10 usuários, os resultados intermediários sempre carregarão todas as milhões de linhas decidíveis. Somente no final próximo o mecanismo se juntará à subconsulta limitada e eliminará tudo, exceto 10 linhas.

    Como você pode acelerar a consulta lenta?

    ANALYZE poderia fornecer algumas informações adicionais ao planejador de consultas que poderiam ajudar a escolher o melhor plano. Você diz que as tabelas maiores têm 2 milhões de registros, mas o planejador de consultas estima 12 milhões de registros cada, então as estatísticas devem estar realmente erradas.

    Mas sugiro que você reescreva sua consulta, movendo a subconsulta para cima na lista para dar uma sugestão ao planejador de consultas para começar calculando a subconsulta:

    SELECT d.*,
           t.*,
           u.id  AS ass_to_id,
           u.email AS ass_to_email,
           s.sid AS ass_to_authority
    FROM  (SELECT t.decidable_id, t.transaction_date
                   FROM decidables_transactions_mv t
                   ORDER BY t.transaction_date DESC, t.decidable_id DESC
                   LIMIT 10) AS decidables_table 
             JOIN decidables d ON d.id = decidables_table.decidable_id
             JOIN decidables_transactions t ON d.id = t.decidable_id
             LEFT JOIN users u ON d.assigned_to = u.id AND u.deleted_at IS NULL
             LEFT JOIN authorities a ON a.user_id = u.id
             LEFT JOIN acl_sid s ON a.sid_id = s.id
             -- some more joins omitted for simplicity
            
    ORDER BY t.transaction_date DESC, t.decidable_id DESC;
    
    • 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