Pesquisa de texto completo do Postgres com várias colunas, por que concatenar no índice e não no tempo de execução?

10

Eu encontrei a pesquisa de texto completo no postgres nos últimos dias e estou um pouco confuso sobre a indexação ao pesquisar em várias colunas.

Os documentos do postgres falam sobre a criação de um ts_vectoríndice em colunas concatenadas, assim:

CREATE INDEX pgweb_idx ON pgweb 
    USING gin(to_tsvector('english', title || ' ' || body));

que eu posso pesquisar assim:

... WHERE 
      (to_tsvector('english', title||' '||body) @@ to_tsquery('english', 'foo'))

No entanto, se eu quisesse pesquisar apenas o título, às vezes apenas o corpo e, às vezes, ambos, precisaria de três índices separados. E se eu adicionasse em uma terceira coluna, isso poderia ser potencialmente 6 índices, e assim por diante.

Uma alternativa que eu não vi nos documentos é apenas indexar as duas colunas separadamente e usar uma WHERE...ORconsulta normal :

... WHERE
      (to_tsvector('english', title) @@ to_tsquery('english','foo'))
    OR
      (to_tsvector('english', body) @@ to_tsquery('english','foo'))

O benchmarking dos dois em ~ 1 milhão de linhas parece não ter basicamente nenhuma diferença no desempenho.

Então, minha pergunta é:

Por que eu gostaria de concatenar índices como esse, em vez de apenas indexar colunas individualmente? Quais são as vantagens / desvantagens de ambos?

Meu melhor palpite é que, se eu soubesse com antecedência, só desejaria pesquisar nas duas colunas (nunca uma de cada vez) e precisaria apenas de um índice concatenando os que usam menos memória.

latentflip
fonte
Não tenho muita certeza de como concatenar a titleentrada bodye indexar isso daria muito valor, embora eu esteja aberto à correção. Eu provavelmente ficaria indexando-os separadamente. Além disso, se foi algo excêntrico que exigisse a concatenação, acho que você poderia executar a consulta ad-hoc.
swasheck
Você está correto em seu palpite. Gostaria de encorajá-lo a responder a si mesmo, se mais ninguém responder, estilo Jeopardy aqui.
jcolebrand

Respostas:

3

Não, você não precisa de índices separados. Use o recurso de pesos. Eles são apenas um rótulo que você pode consultar. Você pode ter até quatro rótulos para consultar (AD).

--search any "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick'::tsquery; --true

--search B "field" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:B'::tsquery; --false

--search B or C "fields" for quick:
select 'quick:1A brown:2B quick:3C'::tsvector @@ 'quick:BC'::tsquery; --true

Convém concatenar tsvectors, para poder aplicar pesos a eles separadamente e montá-los:

select
  setweight( name_column::tsvector, 'A') || setweight( phone_column::tsvector, 'B');
Neil McGuigan
fonte
2

Na verdade, a alternativa seria usar onde com OR , e não AND .

Se você possui um índice no tsvector (corpo + título) e está pesquisando nele, as palavras pesquisadas podem estar no título OU no corpo.

Além disso - ao testar, verifique se você possui um número razoável de linhas na tabela.

Caso mais simples, que deve mostrar boa diferença: encontre duas palavras - uma delas com grande probabilidade de estar no título. e o outro - é muito provável que esteja no corpo. Mas verifique se não há muitas linhas que correspondam aos dois critérios. Por exemplo - você pode ter 30% da palavra "depesz" no corpo. Você também tem ~ 30% de chance de ter "mysql" no título. Mas ter "depesz e mysql" em qualquer um dos campos na mesma linha é muito improvável. E depois verifique o desempenho com esses índices.


fonte
Ha, bom local, em OR vs AND eu vou atualizar a pergunta. Eu fiz isso com linhas 1 milhão - não podia ser incomodado à espera de mais para inserir :)
latentflip
11
Obrigado por cair por depesz - estamos recebendo muito poucos postgres perguntas nos dias de hoje, então eu espero que você vai ficar por aqui :-)
Jack diz tentativa topanswers.xyz
@ Jack: não tenho certeza se vou - achei sites de stackexchange cada vez menos utilizáveis. Geralmente, tento obter RSS, mas nos sites stackexchange rss é praticamente inútil - muita poluição na edição de perguntas antigas.
Criei um feed rss para você aqui - você está disposto a tentar? Estou feliz em colocar o esforço na filtragem de coisas que você não são susceptíveis de estar interessado em ganhar a chance de você mais envolvidos no local :-)
Jack diz tentar topanswers.xyz
Jack :) Vou morder - inscrito.