Skip to content
This repository has been archived by the owner on Oct 2, 2023. It is now read-only.

Melhorar a busca no conteúdo dos arquivos #124

Open
anapaulagomes opened this issue May 22, 2020 · 8 comments
Open

Melhorar a busca no conteúdo dos arquivos #124

anapaulagomes opened this issue May 22, 2020 · 8 comments

Comments

@anapaulagomes
Copy link
Contributor

anapaulagomes commented May 22, 2020

Atualmente as bases de dados do painel tem usado a busca simples, que é mais lenta e cara em termos computacionais. Já temos uma busca com full-text search mas pode ser mais rápida e apresentar resultados mais satisfatórios ao buscar no conteúdo dos arquivos.

@anapaulagomes anapaulagomes changed the title Usar full text search nas buscas do conteúdo dos arquivos através de outras bases Melhorar a busca no conteúdo dos arquivos Dec 29, 2020
@andrewsmedina
Copy link
Contributor

@anapaulagomes temos algum exemplo de busca que está lenta?

@andrewsmedina
Copy link
Contributor

andrewsmedina commented Jan 5, 2021

Como pode ser visto nesse post: https://findwork.dev/blog/optimizing-postgres-full-text-search-in-django/, a forma mais performática em se tratando de full text search com postgres é usando um campo específico para armazenar o search vector e usar um índice GIN ou GiST.

O projeto já segue essas práticas, como poder ver aqui https://github.com/andrewsmedina/maria-quiteria/blob/main/datasets/models.py#L65 e aqui https://github.com/andrewsmedina/maria-quiteria/blob/main/datasets/models.py#L70

Rodando local as queries de busca tem executado bem rapidamente (é possível verificar isso usando o debug toolbar) e imprimindo a query e o explain da query podemos ver que o índice e o campo com o serch vector estão sendo utilizados:

(Pdb) print(queryset.query)
SELECT "datasets_gazette"."id", "datasets_gazette"."created_at", "datasets_gazette"."updated_at", "datasets_gazette"."crawled_at", "datasets_gazette"."crawled_from", "datasets_gazette"."notes", "datasets_gazette"."date", "datasets_gazette"."power", "datasets_gazette"."year_and_edition", "datasets_gazette"."is_legacy" FROM "datasets_gazette" INNER JOIN "datasets_file" ON ("datasets_gazette"."id" = "datasets_file"."object_id" AND ("datasets_file"."content_type_id" = 8)) WHERE "datasets_file"."search_vector" @@ plainto_tsquery(portuguese::regconfig, Secretaria  Municipal da Fazenda) ORDER BY "datasets_gazette"."date" DESC NULLS LAST, "datasets_gazette"."id" DESC
(Pdb) print(queryset.explain())
Sort  (cost=52.33..52.33 rows=1 width=212)
  Sort Key: datasets_gazette.date DESC NULLS LAST, datasets_gazette.id DESC
  ->  Nested Loop  (cost=40.28..52.32 rows=1 width=212)
        ->  Bitmap Heap Scan on datasets_file  (cost=40.00..44.02 rows=1 width=4)
              Recheck Cond: (search_vector @@ '''secret'' & ''municipal'' & ''fazend'''::tsquery)
              Filter: (content_type_id = 8)
              ->  Bitmap Index Scan on datasets_fi_search__52321c_gin  (cost=0.00..40.00 rows=1 width=0)
                    Index Cond: (search_vector @@ '''secret'' & ''municipal'' & ''fazend'''::tsquery)
        ->  Index Scan using datasets_gazette_pkey on datasets_gazette  (cost=0.28..8.30 rows=1 width=212)
              Index Cond: (id = datasets_file.object_id)

Se em produção a pesquisa está com problemas de performance, eu penso em duas hipóteses:

  • será que o índice GIN foi criado em produção? Podemos verificar isso com o debug toolbar ou fazendo o explain da query tanto no django como no postgres.
  • será que não é outra coisa que está afetando a performance? Isso também pode ser investigado usando o debug toolbar.

@anapaulagomes essas hipóteses fazem sentido? Como proceder aqui?

@andrewsmedina andrewsmedina removed their assignment Jan 5, 2021
@anapaulagomes
Copy link
Contributor Author

O @andrewsmedina descobriu que o índice não está funcionando corretamente em produção (na verdade, não está funcionando). Dado que vamos mudar a infra em breve (🙏🏽), vamos deixar como está por hora e revisitar essa issue quando a migração for feita (#134).

@geraldo-castro
Copy link

@anapaulagomes Com a mudança de infra feita, cê acha que podemos avaliar a performance dessa busca?

@anapaulagomes
Copy link
Contributor Author

Sim, tudo já foi migrado. 🚀 Pode checar se funciona local e depois na Absam (a galera do canal #infraestrutura do nosso Discord pode dar mais informações e eu posso ajudar com as credenciais tb). @geraldo-castro

@anapaulagomes
Copy link
Contributor Author

anapaulagomes commented Sep 25, 2021

Configurei o pghero hoje. Vou deixar alguns dias rodando por lá e posto os resultados aqui. Nesse PR habilito os campos que estavam causando gargalos: #401.

cc @turicas @cuducos

@turicas
Copy link

turicas commented Sep 27, 2021

As otimizações iniciais que eu sugeriria já estão feitas (popular o vetor em segundo plano numa coluna dedicada e criar o índice do tipo GIN nessa coluna), mas talvez dê pra melhorar a forma como o Django Admin faz as buscas (pode ser que o ordering do model, por exemplo, esteja influenciando em não usar o índice que existe). Proponho o seguinte:

  1. Monitorar as consultas SQL que o Django Admin está fazendo, para então selecionar as mais custosas e daí entender o porquê da demora com o EXPLAIN. Isso pode ser feito de 2 formas:
  1. Verificar a possibilidade de:
  • Colocar tudo que deve ser buscável na coluna do vetor de busca, assim o Django procura num lugar só, em vez de fazer filtros em múltiplas colunas (que não estão indexadas juntas); ou
  • Indexar todas as colunas que precisam ser buscadas juntamente com o vetor de busca

Notas: no caso de colocar tudo na coluna do vetor de busca:

  • É possível adicionar pesos diferentes aos dados de cada coluna (exemplo: peso maior para o sumário e menor para o texto que vem do Tika)
  • Precisarão ser alteradas as classes ModelAdmin, o management command search_vector e criar uma migração de dados pra re-popular a coluna com os novos dados em produção
  • O comando de indexação ficará mais lento por conta do join entre modelo especializado e arquivo correspondente, mas creio que isso não será um impeditivo. Nesse caso o comando precisaria só atualizar os registros que foram afetados com o resultado do crawler, então a quantidade de registros atualizados não deve ser muito grande.

@exageraldo
Copy link
Member

Saiu um artigo hoje falando um pouco sobre esse tópico.
Deixando o link aqui pra caso alguem queira entender mais/ganhar mais contexto. 🤗

Basic and Full-text Search with Django and Postgres

@anapaulagomes anapaulagomes self-assigned this May 24, 2023
@anapaulagomes anapaulagomes pinned this issue May 24, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants