Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Was ist der beste Weg, um eine Substring-Suche in SQL zu implementieren?

Schauen Sie sich meine Präsentation an Practical Fulltext Search in MySQL .

Ich habe verglichen:

Heute würde ich Apache Solr verwenden , wodurch Lucene zu einem Dienst mit einer Reihe zusätzlicher Funktionen und Tools wird.

Zu Ihrem Kommentar:Aha, okay, nein. Keine der von mir erwähnten Volltextsuchfunktionen wird helfen, da sie alle von einer Art Wortgrenzen ausgehen

Die andere Möglichkeit, beliebige Teilstrings effizient zu finden, ist das N-gram sich nähern. Erstellen Sie im Grunde einen Index aller möglichen Folgen von N Buchstaben und zeigen Sie auf die Zeichenfolgen, in denen die jeweilige Folge vorkommt. Typischerweise geschieht dies mit N=3 oder einem Trigramm , da dies ein Kompromiss zwischen dem Abgleich längerer Teilstrings und dem Halten des Index auf einer überschaubaren Größe ist.

Ich kenne keine SQL-Datenbank, die die N-Gramm-Indizierung transparent unterstützt, aber Sie könnten sie selbst mit einem invertierten Index einrichten :

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

Füllen Sie es jetzt auf die harte Tour:

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

Das dauert natürlich noch eine ganze Weile! Aber sobald es fertig ist, können Sie viel schneller suchen:

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

Natürlich könnten Sie nach Mustern suchen, die länger als drei Zeichen sind, aber der invertierte Index hilft immer noch, Ihre Suche einzugrenzen:

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