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 / 253084
Accepted
collimarco
collimarco
Asked: 2019-11-13 09:19:35 +0800 CST2019-11-13 09:19:35 +0800 CST 2019-11-13 09:19:35 +0800 CST

PostgreSQL NOT IN array consulta lenta

  • 772

Eu tenho uma grande tabela com milhões de linhas. Cada linha tem um campo de matriz tags. Eu também tenho o índice GIN adequado no tags.

Contar as linhas que possuem uma tag é rápido (~7s):

SELECT COUNT(*) FROM "subscriptions" WHERE (tags @> ARRAY['t1']::varchar[]);

No entanto, contar as linhas que não possuem uma tag é extremamente lento (~70s):

SELECT COUNT(*) FROM "subscriptions" WHERE NOT (tags @> ARRAY['t1']::varchar[]);

Eu também tentei outras variantes, mas com os mesmos resultados (~70s):

SELECT COUNT(*) FROM "subscriptions" WHERE NOT ('t1' = ANY (tags));

Como posso tornar a operação "não em array" rápida?

postgresql performance
  • 3 3 respostas
  • 4310 Views

3 respostas

  • Voted
  1. Best Answer
    collimarco
    2019-11-14T08:25:32+08:002019-11-14T08:25:32+08:00

    Eu resolvi graças a Jeff Janes na lista de discussão pgsql-performance:

    O índice GIN não foi usado pelo PostgreSQL para a operação "NOT". A criação de um índice Btree em todo o array resolveu o problema, permitindo uma varredura apenas de índice. Agora, a consulta leva apenas alguns milissegundos em vez de minutos.

    • 4
  2. Erwin Brandstetter
    2019-11-13T09:41:02+08:002019-11-13T09:41:02+08:00

    Se 't1' for uma tag rara, a contagem de linhas que não possuem uma tag resultará na contagem da maioria dos seus "milhões de linhas". E mesmo que 't1' seja muito comum, contar mais do que alguns por cento de linhas do índice não é uma melhoria em relação a uma varredura sequencial. De qualquer forma, isso nunca será muito rápido. Índices não vão ajudar.

    Se você tiver que fazer várias contagens excluindo tags raras - e o número total de linhas não mudar nesse meio tempo (ou a alteração mínima não importa), uma possível otimização seria obter a contagem total de linhas uma vez (lento) e subtraia a (pequena) contagem de linhas com a tag (rápido com índice correspondente) ...

    Dependendo dos requisitos exatos e do seu caso de uso completo, pode haver outros atalhos. Ver:

    • Maneira rápida de descobrir a contagem de linhas de uma tabela no PostgreSQL

    Resumindo, os índices normalmente só podem ajudar a identificar uma porcentagem relativamente pequena de linhas da tabela. BTW, IN, = ANY()e os operadores de contenção @>são ferramentas relacionadas, mas com diferenças sutis. Índices GIN normalmente suportam apenas operadores de array apropriados. Ver:

    • O PostgreSQL pode indexar colunas de array?

    Você pode obter algo usando arrays inteiros em combinação com operadores e um índice baseado em uma classe de operador fornecida pelo intarraymódulo adicional. Altamente otimizado, mas não pode desafiar os principais.

    Você também pode combinar any mixture of tags that the row must have or must not havecomo você comentou em uma query_intexpressão .

    • 1
  3. Morris de Oryx
    2019-11-13T12:27:49+08:002019-11-13T12:27:49+08:00

    Você já teve uma boa resposta, então aqui está um pouco mais para arquivar em alimento para reflexão. Primeiro, sua pergunta me lembrou de uma técnica que soa interessante:

    https://heap.io/blog/engineering/running-10-million-postgresql-indexes-in-production

    Eu estaria interessado em comentários daqueles que tentaram tal estratégia.

    Como outro pensamento, outra opção é manter suas próprias tabelas de frequência para tags e sua ocorrência. Isso pode fornecer informações para orientar seu próprio gerador de código. A ideia aqui é que o planejador/otimizador de consulta genérico nunca pode saber tanto sobre seus dados específicos quanto você. Com contagens de frequência, mesmo contagens aproximadas razoavelmente boas, você pode criar consultas diferentes para enviar ao Postgres para casos diferentes.

    Concretizando essa ideia de contagem de frequência

    Elaborando um pouco aqui como minha resposta abreviada original não estava clara. A noção aqui é que você pode manter uma tabela de contagens de frequência, como tag_countcom tags exclusivas e uma contagem. Esses pequenos dados permitem testar quão comuns são as tags em uma consulta antes de gerar a consulta real para o Postgres. Este plano "simples" depende de várias coisas, algumas das quais podem não ser verdadeiras no seu caso:

    • Você tem o código que está compondo as consultas que podem ser modificadas para fazer essa etapa de pré-processamento para descobrir a melhor forma de compor a consulta.

    • Você pode encontrar maneiras de usar as contagens de frequência para ajudar o planejador a fazer um trabalho melhor.

    • Existe alguma maneira de você executar o código de atualização da contagem de frequência.

    • Existe alguma maneira de manter as contagens com fidelidade adequada e sem atolar o sistema.

    Esse último ponto é um tópico enorme, obviamente. A maneira mais simples (conceitualmente) é um gatilho para adicionar/modificar/excluir que encontra as tags antigas e novas e ajusta as contagens de acordo. Não é a solução mais eficiente e um potencial gargalo. Existem muitos, muitos projetos alternativos. (Um gatilho em nível de instrução com uma tabela de filas pós-reconciliação seria um design alternativo que não é um gargalo.) Honestamente, ainda não conheço as estratégias de melhor desempenho para atualizações incrementais no Postgres. Eu esbocei ~ 10 estratégias para mim alguns meses atrás, mas não voltei para testar e comparar soluções. Outras pessoas neste fórum usam o Postgres há muito tempo e são super inteligentes e prestativas. Então, se esse tipo de solução é o que você procura, vale a pena perguntar novamente.

    • 1

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