maria-quiteria icon indicating copy to clipboard operation
maria-quiteria copied to clipboard

Melhorar a busca no conteúdo dos arquivos

Open anapaulagomes opened this issue 4 years ago • 8 comments

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 avatar May 22 '20 07:05 anapaulagomes

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

andrewsmedina avatar Dec 30 '20 17:12 andrewsmedina

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 avatar Jan 05 '21 16:01 andrewsmedina

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).

anapaulagomes avatar Jan 06 '21 09:01 anapaulagomes

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

geraldo-castro avatar Sep 08 '21 11:09 geraldo-castro

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 avatar Sep 08 '21 11:09 anapaulagomes

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: https://github.com/DadosAbertosDeFeira/maria-quiteria/pull/401.

cc @turicas @cuducos

anapaulagomes avatar Sep 25 '21 12:09 anapaulagomes

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.

turicas avatar Sep 27 '21 18:09 turicas

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

exageraldo avatar Oct 11 '21 21:10 exageraldo