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 / 249022
Accepted
Morris de Oryx
Morris de Oryx
Asked: 2019-09-18 18:15:50 +0800 CST2019-09-18 18:15:50 +0800 CST 2019-09-18 18:15:50 +0800 CST

Índice de expressão em uma coluna citext ignorado, por quê?

  • 772

Executando em RDS com cerca de 32 milhões de linhas.

PostgreSQL 11.4 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11), 64-bit

Também testando localmente no macOS com cerca de 8 milhões de linhas.

PostgreSQL 11.5 on x86_64-apple-darwin16.7.0, compiled by Apple LLVM version 8.1.0 (clang-802.0.42), 64-bit

Eu tenho uma coluna chamada old_valueque é do tipo citext. Eu já perguntei sobre isso, mas postei muitos dos meus passos de descoberta ao longo do caminho . Aqui está uma versão resumida que eu espero que chegue ao ponto.

Fundo

Eu tenho uma tabela de log de alterações de campo chamada record_changes_log_detail com 32 milhões de linhas e em crescimento que inclui um campo citext chamado old_value.

Os dados são muito distorcidos. A maioria dos valores são menos de uma dúzia de caracteres, alguns são mais de 5.000.

O Postgres engasga com valores grandes com um erro sobre as entradas da árvore B serem limitadas a 2172 caracteres. Portanto, acredito que para uma árvore B, preciso substringir o valor de origem.

O interesse principal dos meus usuários é uma pesquisa =, uma pesquisa que começa com e, às vezes, uma pesquisa contém esta substring. Então = string% e %string%

Metas

Crie um índice que suporte essas pesquisas que o planejador usa.

Tentou e falhou

Uma árvore B reta falha ao construir, em alguns casos, devido a valores longos.

Uma expressão B-tree como esta é construída, mas não é usada

CREATE INDEX record_changes_log_detail_old_value_ix_btree
    ON  record_changes_log_detail 
    USING btree (substring(old_value,1,1024));

Adicionar text_pattern_opts não ajuda.

CREATE INDEX record_changes_log_detail_old_value_ix_btree
    ON  record_changes_log_detail 
    USING btree (substring(old_value,1,1024) text_pattern_opts);

Tentei e funciona parcialmente

Um índice de hash funciona, mas apenas para igualdade. (Como diz na lata.)

Este é o mais próximo que cheguei do sucesso:

CREATE INDEX record_changes_log_detail_old_value_ix_btree
    ON record_changes_log_detail 
    USING btree (old_value citext_pattern_ops);

Isso funciona para qualidade, mas não para LIKE. As notas de lançamento do PG 11 dizem que deve funcionar para LIKE:

https://www.postgresql.org/docs/11/release-11.html

Por "trabalho" quero dizer "o índice é usado".

Não consegui substring com sucesso com essa abordagem.

O que as pessoas fazem nesta situação com campos de citexto?

postgresql index
  • 3 3 respostas
  • 544 Views

3 respostas

  • Voted
  1. jjanes
    2019-09-19T04:56:37+08:002019-09-19T04:56:37+08:00

    Edite sua pergunta, em vez de postar respostas que não a respondam.

    Se você criar um índice na expressão substring(old_value,1,1024), esse índice só poderá ser usado se a consulta envolver substring(old_value,1,1024).

    Embora seja teoricamente possível provar que isso old_value='foo'implica que substring(old_value,1,1024)='foo'(e, portanto, a contrapositiva a isso) se você tiver conhecimento suficiente sobre as partes internas da substring, o PostgreSQL não tenta provar isso . Você precisa escrever a consulta de forma que nenhuma prova seja necessária.

    • 3
  2. Best Answer
    Laurenz Albe
    2019-09-19T22:22:21+08:002019-09-19T22:22:21+08:00

    É incomum indexar uma coluna tão longa inteiramente.

    Três ideias:

    1. Modifique a consulta assim:

      WHERE substring(old_value, 1, 100) LIKE substring(pattern, 1, 100)
        AND old_value LIKE pattern
      

      ( patternaqui seria a string padrão, algo como 'string%'.)

      Então um índice b-tree substring(old_value, 1, 100)pode ser usado (se o padrão não começar com um caractere curinga, é claro).

    2. Dependendo dos requisitos exatos (você está pesquisando palavras completas ou prefixos de palavras em um texto em linguagem natural ou não), a pesquisa de texto completo pode ser uma boa solução.

    3. Outra opção são os índices de trigramas :

      CREATE INDEX ON record_changes_log_detail USING gin (old_value gin_trgm_ops);
      

      Isso requer que a pg_trgmextensão seja instalada.

      Esse índice também funcionará para padrões de pesquisa que começam com um curinga. Para um bom desempenho, imponha um comprimento mínimo na string de pesquisa.

    • 2
  3. Morris de Oryx
    2019-09-20T04:39:06+08:002019-09-20T04:39:06+08:00

    Estou de volta para encerrar esta questão. Seguindo uma sugestão de Laurenz Albe, experimentei a implementação de trigrama do Postgres. Eles governam!

    DROP INDEX IF EXISTS record_changes_log_detail_old_value_ix_tgrm;
    CREATE INDEX record_changes_log_detail_old_value_ix_tgrm
        ON record_changes_log_detail 
        USING gin (old_value gin_trgm_ops);
    

    O segredo aqui quando você está usando citext é converter seu valor para ::text, assim:

    select * from record_changes_log_detail 
    where old_value::text LIKE '%Gold Kerrison Neuro%';
    

    Executando isso com a análise de explicação confirma que o índice é usado. Percebi que tenho que usar LIKE para uma pesquisa =, mas tudo bem.

    • 0

relate perguntas

  • Quanto "Padding" coloco em meus índices?

  • Sequências Biológicas do UniProt no PostgreSQL

  • O que significa "índice" em RDBMSs? [fechado]

  • Como criar um índice condicional no MySQL?

  • 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