Mysql
 sql >> Base de données >  >> RDS >> Mysql

Quelle est la meilleure façon d'implémenter une recherche de sous-chaîne en SQL ?

Découvrez ma présentation Recherche en texte intégral pratique dans MySQL .

J'ai comparé :

Aujourd'hui, ce que j'utiliserais est Apache Solr , qui place Lucene dans un service avec un tas de fonctionnalités et d'outils supplémentaires.

Re votre commentaire:Aha, d'accord, non. Aucune des fonctionnalités de recherche en texte intégral que j'ai mentionnées ne va vous aider, car elles supposent toutes une sorte de limites de mots

L'autre façon de trouver efficacement des sous-chaînes arbitraires est le N-gram approcher. Fondamentalement, créez un index de toutes les séquences possibles de N lettres et pointez sur les chaînes où chaque séquence respective se produit. Cela se fait généralement avec N=3, ou un trigramme , car il s'agit d'un compromis entre la mise en correspondance de sous-chaînes plus longues et le maintien de l'index à une taille gérable.

Je ne connais aucune base de données SQL prenant en charge l'indexation N-gram de manière transparente, mais vous pouvez la configurer vous-même en utilisant un index inversé :

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

Maintenant, remplissez-le à la dure :

insert into trigram_matches
  select t.trigram, d.document_id
  from trigrams t join mytable d
    on d.textcolumn like concat('%', t.trigram, '%');

Bien sûr, cela prendra un certain temps! Mais une fois que c'est fait, vous pouvez chercher beaucoup plus rapidement :

select d.*
from mytable d join trigram_matches t
  on t.document_id = d.document_id
where t.trigram = 'abc'

Bien sûr, vous pourriez rechercher des modèles de plus de trois caractères, mais l'index inversé aide toujours à affiner votre recherche :

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%';