FULLTEXT поиск в MySQL - подойдет ли?

12
vrom
На сайте с 15.12.2005
Offline
84
4913

нужно искать в базе по одному полю keywords

Сейчас это выглядит так:

MySQL 4.0.x


Показывает записи 0 - 29 (802 всего, Запрос занял 0.4808 сек)
SQL-запрос:
SELECT DISTINCT items . *
FROM items, sections, items_sections_mm
WHERE (
items.keywords LIKE 'woman'
OR items.keywords LIKE '% woman'
OR items.keywords LIKE 'woman %'
OR items.keywords LIKE '% woman %'
)
AND (
items.keywords LIKE 'winter'
OR items.keywords LIKE '% winter'
OR items.keywords LIKE 'winter %'
OR items.keywords LIKE '% winter %'
)
AND items.pid
IN ( 4, 5, 22, 23, 24, 40, 42, 38, 35, 25, 26, 45, 101, 46, 128, 1 )
AND sections.uid
IN ( 722, 813, 636, 451, 717, 669, 794, 797, 910, 804, 648, 788, 584, 567, 895, 654, 807, 430, 804, 887, 802, 801, 591, 715, 107, 806, 602, 108, 799, 720, 798, 927 )
AND sections.uid = items_sections_mm.uid_foreign
AND items_sections_mm.uid_local = items.uid
LIMIT 0 , 30

Когда здесь стояло ORDER BY items.uid - запрос выполнялся 9.2201 сек.

COUNT выполняется сейчас примерно столько же - я догадываюсь почему - число записей - 170 000.

В дальшейшем - до 1 500 000.

Что хочется:

Показывает записи 0 - 29 (804 всего, Запрос занял 0.1064 сек)

SQL-запрос:
SELECT DISTINCT items . *
FROM items, sections, items_sections_mm
WHERE MATCH (
keywords
)
AGAINST (
'+woman +winter'
IN BOOLEAN
MODE
)
AND items.pid
IN ( 4, 5, 22, 23, 24, 40, 42, 38, 35, 25, 26, 45, 101, 46, 128, 1 )
AND sections.uid
IN ( 722, 813, 636, 451, 717, 669, 794, 797, 910, 804, 648, 788, 584, 567, 895, 654, 807, 430, 804, 887, 802, 801, 591, 715, 107, 806, 602, 108, 799, 720, 798, 927 )
AND sections.uid = items_sections_mm.uid_foreign
AND items_sections_mm.uid_local = items.uid
LIMIT 0 , 30

Показывает записи 0 - 0 (1 всего, Запрос занял 1.3104 сек)

SQL-запрос:
SELECT COUNT( DISTINCT items.uid )
FROM items, sections, items_sections_mm
WHERE MATCH (
keywords
)
AGAINST (
'+woman +winter'
IN BOOLEAN
MODE
)
AND items.pid
IN ( 4, 5, 22, 23, 24, 40, 42, 38, 35, 25, 26, 45, 101, 46, 128, 1 )
AND sections.uid
IN ( 722, 813, 636, 451, 717, 669, 794, 797, 910, 804, 648, 788, 584, 567, 895, 654, 807, 430, 804, 887, 802, 801, 591, 715, 107, 806, 602, 108, 799, 720, 798, 927 )
AND sections.uid = items_sections_mm.uid_foreign
AND items_sections_mm.uid_local = items.uid
LIMIT 0 , 30

Вопросы

1) какой верхний предел количества записей, чтобы выполнение запроса было в пределах 3 сек ?

2) имеет ли смысл ставить MySQL 5.1 - там вроде что-то улучшили c FULLTEXT

3) опыта по таким вещам у меня мало - может быть есть какие-то лежащие на поверхности простые решения ?

Cвой индексатор, который парсит поле keywords и делает 2 таблицы:

words

items_words_mm

я уже написал... но что-то не нравится такой путь.

Вроде он не даст обойтись одним-двумя запросами.

Ставить mnogosearch для поиска по базе могу, но очень этого не хочется, поскольку потребуется много переделок.

Заранее благодарю за помощь.

Разработка интернет-магазинов на CS-Cart (http://typo3lab.ru/cs-cart.html). Почему CS-Cart рулит? (http://typo3lab.ru/cs-cart.html#c967)
I
На сайте с 26.05.2001
Offline
64
#1

MySQL fulltext search вполне себе рулит.

Я вот его собираюсь использовать в ближайшее время вот здесь http://punto.ru/ctl. Точные предел предсказать сложно, но несколько десятков тысяч страниц должен потянуть без проблем, см, например, отзывы здесь (как раз про пятерку) .

Приходите завтра, завтра будет! (http://itman666.livejournal.com)
ЗодчийТеней
На сайте с 13.02.2006
Offline
11
#2

тема уже обсуждалась /ru/forum/37822

поиск в любом случае будет идти через LIKE чтобы вы не писали, все структуры MATCH AGAINST это лишь частные интерпретации LIKE дающие вам возможность меньше ломать голову над составлением запроса, отсюда и меньшая скорость работы, первый ваш запрос избыточен, его можно и нужно на порядок укоротить. скорость выборки будет во многом завесить от мощности используемого оборудования. включите кешерование запросов, это позволит в некоторых случаях меньше насиловать базу. переходить на 5,1 смысла нет, она еще слишком «корявая» по сравнению с 4-й версией. выигрыша в производительности при переходе на нее нет.

Я, однако, не скажу, что все иллюзии или бред нашего ума нужно называть сумасшествием. Эразм Роттердамский "Похвала глупости".
I
На сайте с 26.05.2001
Offline
64
#3

Зодчий, Вы, АПСОЛЮТНО, АПСОЛЮТНО не правы. Тема-то подымалсь, но проблема в ней обсуждалась немножечко другая (если не сказать совсем другая). Почему у человека не находятся результаты по некоторым ключевым словам. А ответ простой: потому что искать нужно в BOOLEAN mode. Вопрос второй: релевантность результатов. Конечно, для больших баз будет не очень релеватно, потому что поиск без учета расстояний. Но если добавить морфологию, чуть-чуть подкрутить релевантность, чтобы тайтл шел с большим весом, то для 50-100 тысяч записей вполне пойдет. Вопрос третий про лайк. Это неправда, в MySQL реализована векторная модель. Читайте не русскую документацию, а вот здесь. В частности, это означает, что LIKE, скорее всего, будет работать ощутимо медленнее.

ЗодчийТеней
На сайте с 13.02.2006
Offline
11
#4

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

vrom
На сайте с 15.12.2005
Offline
84
#5

Спасибо всем!

1. релевантность мне не важна.

Поиск в одном поле keywords.

Это фотоагентство. Когда люди ищут по базе из 1000000 фотографий, то они набирают так:

woman - 300000
woman winter -> 3000
woman winter dog -> 300

и потом уже смотрять эти 300 фоток

2. Количество записей в таблице - до 1 500 000. Это при том, что еще есть 300 категорий, которые необходимо учитывать в поиске.

Это несколько меняет ситуцию.

3. В поле keywords огромной количество вот такой бяки:

grape_hyacinth ©Some_Name single_subject natural_light...

Это сильно увеличит размер словарной базы. Но это надо сохранять.

Доку читать и архитектурой и тонкой настройкой мускла разбираться придется по любому.. это я уже понял.

ЗодчийТеней
На сайте с 13.02.2006
Offline
11
#6

/ru/forum/comment/1082372

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

vrom
На сайте с 15.12.2005
Offline
84
#7

этого вам хватит с головой, без всяких тонких настроек и изучения спецификаций мускуля.

не понимаю :-)

$query = "SELECT `search`.*, "
." IF (search like '%".$text."%', 3*10, 0) "
." + IF (search LIKE '%".str_replace(" ", "%', 9, 0) + IF (search LIKE '%", $text)."%', 9, 0) AS relev"
." FROM `search` "
." WHERE (`search`.`search` LIKE '%".str_replace(" ", "%' OR `search`.`search` LIKE '%", $text)."%') "
." ORDER BY relev DESC";

Релевантность мне вообще не нужна.

Что в этом примере есть, кроме LIKE %man%

который найдет мужчин (man) в тех местах где есть только женщины (woman) ?

ЗодчийТеней
На сайте с 13.02.2006
Offline
11
#8

выкиньте релевантность, насчет того что он найдет … подкорректируйте допуски под свои нужды и все

vrom
На сайте с 15.12.2005
Offline
84
#9

Сделал - работает вполне пристойно

на запросах типа

SELECT distinct items.*
FROM items, sections, items_sections_mm
WHERE
MATCH (keywords) AGAINST ( '+woman +man +(cat dog) -god -bench' IN BOOLEAN MODE )
....

при 170000 записях в items отрабатывает в пределах 2-4 сек.

K
На сайте с 22.04.2003
Offline
31
Ken
#10

Не очень поятно зачем вы используете (like % woman).

В случае если % стоит в начале строки индекс не учитывается и время выборки жестоко увеличивается.

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий