Slides usados na palestra Full Text Search com Solr, MySQL Full text e PostgreSQL Full Text que apresentei hoje pela manha no #TheDevConf #TDCPOA #TDC2014
Full Text Search com Solr, MySQL Full text e PostgreSQL Full Text
1. Full Text Search com Solr,
MySQL Fulltext e PostgreSQL
Fulltext search
Por que usar? Quando usar? Qual usar?
2. Rodrigo Urubatan
Programador desde 1997
Autor do livro: Ruby on Rails
desenvolvimento fácil e rápido
de aplicações web
http://urubatan.com.br
http://sobrecodigo.com
http://twitter.com/urubatan
http://github.com/urubatan
3. O que é FTS?
Full Text Search é um recurso utilizado
quando precisamos buscar texto de forma
mais eficiente em uma grande massa de dados
Engines de FTS permitem uma maior
flexibilidade que um “like ‘%valor%’"
Normalmente também uma maior performance
4. Quais são as opções disponíveis?
Alguns bancos de dados como o MySQL, o
Postgres e o Oracle possuem engines internas
de FTS
Existem servidores externos também como o
Solr, Sphinx entre outros
6. MySQL
Extremamente fácil de configurar
Bastante rápido
Tem problemas com alguns caracteres, por exemplo não é
possível pesquisar por AT&T
Não necessita esforço adicional para indexar, funciona com
um índice simples
O critério de pesquisa precisa ser fixo para uma query (não é
possível comparar com o valor de um campo)
7. PostgreSQL
Quase tão fácil de configurar quanto o MySQL
Performance semelhante
Interpretador de consultas mais inteligente (é
possível pesquisar por AT&T, mesmo ele buscando
por /AT.T/ )
É necessário uma trigger para atualizar o campo de
cache do ::tsvector
8. Solr
Mais difícil de configurar
Performance espetacular
Extremamente flexível
Necessita de código na aplicação para indexar e
atualizar indices
Pesquisas extremamente rápidas, indexação bastante
lenta se comparada com as outras opções
9. Ok, mas quando vou precisar disto?
Imagina se tu tem um site de noticias e quer
que teus usuários pesquisem pelo texto das
noticias?
Ou tu tem uma lista de empresas e os teus
clientes podem procurar pelo nome ou pelo
código das ações delas?
10. Já pensou em implementar um
Google?
Pesquisar por: +“campo bom” & +agricultura
12. MySQL
alter table companies
add FULLTEXT KEY allfields
(name,ticker_symbol,exchange_symbol);
select * from companies
where match(name,ticker_symbol,exchange_symbol)
against("petrobras");
14. select exchange_symbol, group_concat(name) from companies
where match(name) against("petrobras")
group by exchange_symbol;
3 linhas 0.021s
select exchange_symbol, group_concat(name) from companies
where name like "%petrobras%"
group by exchange_symbol;
3 linhas 4.101s
um like levou 195X o tempo do FTS
15. PostgreSQL
alter table companies
add text tsvector;
CREATE INDEX companies_text ON companies USING gin(text);
update companies
set text = to_tsvector(concat(name,’ ’, ticker_symbol, ‘ ‘,
exchange_symbol);
select * from companies
where text @@ ‘petrobras’::tsquery;
17. select exchange_symbol, array_agg(name) from companies
where text @@ 'petrobras'::tsquery
group by exchange_symbol;
18ms
select exchange_symbol, array_agg(name) from companies
where name like '%petrobras%'
group by exchange_symbol;
2308ms
FTS 128X mais rapido que like
18. Solr
Instalar sunspot_rails e sunspot_solr no projeto rails
Adicionar código para indexar classes:
class Company < ActiveRecord::Base
searchable do
text :name
text :exchange_and_ticker do
"#{self.exchange_symbol}:#{self.ticker_symbol}"
end
end
end
Company.reindex #senta e espera
#versão mais rápida: Company.find_in_batches{|batch| Sunspot.index!(batch)}
19. res = Company.search do
fulltext('petrobras')
end
13.5ms - com configuração de desenvolvimento (rake
sunspot:solr:start)
Company.where("name like ?", “%petrobras%")
4080.5ms
Solr 302X mais rápido que like
20. boosting de resultados
Post.search do
fulltext 'pizza' do
boost(2.0) { with(:featured, true) }
end
end
Post.search do
fulltext 'pizza' do
fields(:body, :title => 2.0)
end
end
21. Resultados Facetados
search = Post.search do
fulltext "pizza"
facet :author_id
end
search.facet(:author_id).rows.each do |facet|
puts "Author #{facet.value} has #{facet.count}
pizza posts!"
end