Что лучший способ состоит в том, чтобы реализовать поиск подстроки в SQL?

У нас есть простая проблема SQL здесь. В varchar столбце мы хотели искать строку где угодно в поле. Что лучший способ состоит в том, чтобы реализовать это для производительности? Очевидно, индекс не собирается помогать здесь, какие-либо другие приемы?

Мы используем MySQL и имеем приблизительно 3 миллиона записей. Мы должны выполнить многие из этих запросов, в секунду поэтому действительно пытающихся реализовать их с лучшей производительностью.

Самый простой способ сделать это, до сих пор:

Select * from table where column like '%search%'

Я должен далее указать, что столбец является на самом деле длинной строкой как "sadfasdfwerwe", и я должен искать "asdf" в этом столбце. Таким образом, они не предложения и пытающийся распознать слово в них. Полнотекстовый поиск все еще помог бы здесь?

8
задан erotsppa 23 July 2010 в 18:01
поделиться

3 ответа

Посмотрите мою презентацию Практический полнотекстовый поиск в MySQL.

Я сравнил:

Сегодня я бы использовал Apache Solr, который превращает Lucene в сервис с кучей дополнительных возможностей и инструментов.


По поводу вашего комментария: Ага, хорошо, нет. Ни одна из упомянутых мною возможностей полнотекстового поиска не поможет, поскольку все они предполагают наличие границ между словами

Другой способ эффективного поиска произвольных подстрок - это подход N-граммы. По сути, создайте индекс всех возможных последовательностей из N букв и укажите строки, в которых встречается каждая соответствующая последовательность. Обычно это делается при N=3, или триграмме, потому что это компромисс между поиском более длинных подстрок и сохранением управляемого размера индекса.

Я не знаю ни одной базы данных SQL, которая бы прозрачно поддерживала индексацию N-грамм, но вы можете настроить ее самостоятельно, используя инвертированный индекс:

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

Теперь заполните ее сложным способом:

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

Конечно, это займет довольно много времени! Но как только это будет сделано, вы сможете искать гораздо быстрее:

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

Конечно, вы можете искать детали длиннее трех символов, но инвертированный индекс все равно помогает значительно сузить поиск:

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%';
15
ответ дан 5 December 2019 в 11:21
поделиться

Если вы хотите найти целые слова, посмотрите на индекс FULLTEXT и MATCH() AGAINST(). И, конечно же, загрузите свой сервер базы данных: кэшируйте результаты в течение соответствующего времени для ваших конкретных нужд.

0
ответ дан 5 December 2019 в 11:21
поделиться

Во-первых, возможно, это проблема с плохо спроектированной таблицей, которая хранит строку с разделителями в одном поле вместо правильного проектирования для создания связанной таблицы. В этом случае вам следует исправить свой дизайн.

Если у вас есть поле с длинным описательным текстом (например, поле примечаний) и поиск всегда осуществляется по целому слову, вы можете выполнить полнотекстовый поиск.

Подумайте, можете ли вы потребовать от пользователей давать вам хотя бы первый символ того, что они ищут, если это обычное поле, такое как Last_name.

Рассмотрите возможность сначала выполнить поиск с точным соответствием и выполнить поиск по шаблону только в том случае, если результаты не возвращаются. Это будет работать, если у вас есть пользователи, которые могут предоставить точные совпадения. Один раз мы проделали это с поиском названий аэропортов, они возвращались очень быстро, если они вводили точное название, и медленнее, если они этого не делали.

Если вы хотите искать только строки, которые не являются словами, которые могут быть где-то в тексте, вы в значительной степени застряли с плохой производительностью.

0
ответ дан 5 December 2019 в 11:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: