SQLite - как вернуть строки, содержащие текстовое поле, содержащее одну или несколько строк?

Мне нужно запросить таблицу в базе данных SQLite, чтобы вернуть все строки в таблице, которые соответствуют заданному набору слов.

Чтобы быть более точным: у меня есть база данных с ~ 80 000 записей. Одно из полей представляет собой текстовое поле, содержащее около 100–200 слов на запись. Что я хочу сделать, так это взять список из 200 ключевых слов из одного слова {"яблоко", "апельсин", "груша",...} и получить набор всех записей в таблице, содержащих хотя бы один ключевых слов в столбце описания.

Сразу очевидный способ сделать это с чем-то вроде этого:

SELECT stuff FROM table 
WHERE (description LIKE '% apple %') or (description LIKE '% orange %') or ... 

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

Этот ответ Лучшая производительность для SQLite Select Statement показался мне близким к тому, что мне нужно, и в результате я создал индекс, но согласно http://www.sqlite.org/optoverview.html sqlite не использует никаких оптимизаций, если оператор LIKE используется с подстановочным знаком % в начале.

Не будучи экспертом по SQL, я предполагаю, что делаю это глупо. Мне было интересно, может ли кто-нибудь с большим опытом предложить более разумный и, возможно, более эффективный способ сделать это?

В качестве альтернативы, есть ли лучший подход, который я мог бы использовать для решения проблемы?


person Sam    schedule 06.01.2011    source источник


Ответы (3)


Использование полнотекстового поиска SQLite будет быстрее, чем запрос LIKE '%...%'. Я не думаю, что есть какая-либо база данных, которая может использовать индекс для запроса, начинающегося с %, поскольку, если база данных не знает, с чего начинается запрос, она не может использовать индекс для его поиска.

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

person Michael Low    schedule 06.01.2011
comment
Спасибо, это точно решает проблему. Я посмотрел на ссылку, и она выглядит идеально. - person Sam; 06.01.2011

Похоже, вам стоит взглянуть на Полнотекстовый поиск. Его внес в SQLite кто-то из Google. Описание:

позволяет пользователю эффективно запрашивать в базе данных все строки, содержащие одно или несколько слов (далее «токены»), даже если таблица содержит много больших документов.

person Nick Fortescue    schedule 06.01.2011

Это та же проблема, что и полнотекстовый поиск, верно? В этом случае вам понадобится помощь БД для создания индексов в этих полях, если вы хотите сделать это эффективно. Быстрый поиск по полнотекстовому поиску SQLite дает эту страницу.

Решение, которое вы правильно идентифицируете как неуклюжее, вероятно, будет выполнять до 200 совпадений с регулярным выражением для каждого документа в худшем случае (т. е. когда документ не соответствует), когда каждое совпадение должно проходить через все поле. Использование индексного подхода будет означать, что ваша скорость поиска не будет зависеть от размера каждого документа.

person sjr    schedule 06.01.2011