Confira minha apresentação Pesquisa prática de texto completo no MySQL .
Eu comparei:
LIKE
predicados- Expressão regular
predicados (não melhor que
LIKE
) - MyISAM FULLTEXT indexação
- Pesquisa do Sphinx
- Apache Lucene
- Indexação invertida
- Google Mecanismo de pesquisa personalizado
Hoje o que eu usaria é o Apache Solr , que coloca o Lucene em um serviço com vários recursos e ferramentas extras.
Re seu comentário:Aha, ok, não. Nenhum dos recursos de pesquisa de texto completo que mencionei ajudará, pois todos assumem algum tipo de limite de palavras
A outra maneira de encontrar substrings arbitrárias com eficiência é o N-gram abordagem. Basicamente, crie um índice de todas as sequências possíveis de N letras e aponte para as strings onde cada sequência respectiva ocorre. Normalmente, isso é feito com N=3 ou um trigrama , porque é um ponto de compromisso entre corresponder substrings mais longas e manter o índice em um tamanho gerenciável.
Não conheço nenhum banco de dados SQL que suporte a indexação de N-gram de forma transparente, mas você pode configurá-lo usando um índice invertido :
create table trigrams (
trigram char(3) primary key
);
create table trigram_matches (
trigram char(3),
document_id int,
primary key (trigram, document_id),
foreign key (trigram) references trigrams(trigram),
foreign key (document_id) references mytable(document_id)
);
Agora preencha-o da maneira mais difícil:
insert into trigram_matches
select t.trigram, d.document_id
from trigrams t join mytable d
on d.textcolumn like concat('%', t.trigram, '%');
Claro que isso vai demorar bastante! Mas uma vez feito, você pode pesquisar muito mais rapidamente:
select d.*
from mytable d join trigram_matches t
on t.document_id = d.document_id
where t.trigram = 'abc'
Claro que você pode estar procurando por padrões com mais de três caracteres, mas o índice invertido ainda ajuda a restringir muito sua pesquisa:
select d.*
from mytable d join trigram_matches t
on t.document_id = d.document_id
where t.trigram = 'abc'
and d.textcolumn like '%abcdef%';