Mysql
 sql >> Database >  >> RDS >> Mysql

Qual è il modo migliore per implementare una ricerca di sottostringhe in SQL?

Guarda la mia presentazione Pratica ricerca fulltext in MySQL .

Ho confrontato:

Oggi quello che userei è Apache Solr , che inserisce Lucene in un servizio con una serie di funzionalità e strumenti extra.

Re il tuo commento:Aha, va bene, no. Nessuna delle funzionalità di ricerca full-text che ho menzionato sarà di aiuto, poiché presuppongono tutte una sorta di limiti di parole

L'altro modo per trovare in modo efficiente sottostringhe arbitrarie è N-gram approccio. Fondamentalmente, crea un indice di tutte le possibili sequenze di N lettere e punta alle stringhe in cui si verifica ciascuna rispettiva sequenza. In genere questo viene fatto con N=3 o un trigramma , perché è un punto di compromesso tra la corrispondenza di sottostringhe più lunghe e il mantenimento dell'indice a una dimensione gestibile.

Non conosco nessun database SQL che supporti l'indicizzazione N-gram in modo trasparente, ma potresti configurarlo tu stesso usando un indice invertito :

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

Ora popolalo nel modo più difficile:

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

Ovviamente ci vorrà un bel po' di tempo! Ma una volta fatto, puoi cercare molto più rapidamente:

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

Ovviamente potresti cercare schemi più lunghi di tre caratteri, ma l'indice invertito aiuta comunque a restringere molto la tua ricerca:

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