Насколько я понял, Sphinx реализует сервер MySQL 4?
Я просто из Erlang коннектился к сфинксу этим драйвером github.com/dizzyd/erlang-mysql-driver и получал кучу ошибок т.к. драйвер поддерживает только MySQL 5, пришлось долго разбираться.
Все несколько затейливее. Мы поддерживаем протокол версии 10, который начиная от версии 4.1 и далее везде, включая 5.x. Ошибки бывают по двум причинам: 1) либо драйвер вместо флагов протокола разбирает еще и текстовый номер версии сервера, зачем-то пытается принимать всякие решения на ее основе, и сходит с ума (это чаще всего); 2) либо наша комбинация флагов оказывается для драйвера шибко неожиданной, и драйвер опять таки сходит с ума. Ну те. драйвера, скажем так, не всегда по одной только публичной спецификации работают и не во всех теоретически возможных случаях корректно ;)
О, пользуясь случаем sphinxsearch.com/bugs/view.php?id=696 — зарепортил, но никто не заревьюил. Проблема все еще актуальна. Если искать по индексу триграмм слово короче 3-х символов, то зависает намертво. Проявляется только в 1.10, в предыдущей версии работало без сбоев.
Интересный костыль для добавления в innoDB функциональности, которая там не нужна.
Для себя я решил давно и прочно, что если нужен поиск по базе, то его нужно делать НЕ средствами базы.
Для мелких таблиц подход из статьи вполне применим, но если нужно искать по полутора гигабайтам, то увы.
Любой полнотекстовый индекс будет весить никак не меньше половины данных.
Как следствие — замедление поиска по мере накопления данных в таблице, блокировки, выход из буфферов и прочие нехорошие вещи.
Абстрагируясь от вышеназванного, хотел бы покритиковать пару моментов. При беглом прочтении видно, что поиск по LIKE не использует индексов (поскольку данные из нескольких колонок конкатенируются вживую). Разумеется, такой запрос будет ужасно медленным. Также в триггерах не нравятся циклы (FOR EACH ROW) — дешевле делать синхронизацию через INSERT INTO mirror_table SELECT * FROM original_table WHERE original_table.id NOT IN (SELECT id FROM mirror_table) и аналогично удаление (обновление останется в цикле, но это обычно достаточно редкая операция).
>> Существует ряд сторонних решений для полнотекстового поиска. Наиболее популярные платформы это Sphinx и проекты на базе Apache Lucene. Их использование лишено смысла при небольших объемах данных (таких как в нашем примере), а иногда просто невозможно в связи с ограничениями (хостер, злой админ, кривые руки и т. д.).
Да, ладно. А предположим у вас в текст в базе лежит словосочетание «красные конфеты». А пользователь на форме в сайте вводит «красная конфета». Как вы средствами MySQL будете обрабатывать эту ситуацию?
Это как раз не сложно. Нужно подключить внешний морфологический движок и делать запрос в базу что-то типа — «красный красная красную… конфета конфеты конфету ...» Естественно необходимо правильно выставить весовые коефициенты
Не буду говорить за Сфинкс, но в Solr (lucene), это проблема без проблем. Поэтому не лучше ли не изобретать велосипед и использовать нормальный поисковый движок.
У каждого решения есть свои плюсы и минусы.
Сфинкс хорошо безусловно, но не позволяет организовать поиск в реальном времени.
Lucene — решает проблему реального времени.
MySql Fulltext search — хорош тем, что не нужно ставить ничего дополнительного.
MySql Fulltext search не является полноценным поиском без морфологического словаря и это есть проблема. Ибо статей подобных этой много. Но вот про морфологический словарь все забывают.
Realtime индексы убогие… Не поддерживают даже поиск по подстроке, стеммеры, морфологию и пр. Т.е. как ввел поисковое слово так его и будет искать. Нужно ручками реализовывать всю обработку (либо при индексировании прогнать текст через морфологическую либу либо при поиске запрос прогнать)
видимо если ее не включать в конфиге, то не поддерживают
а если включать
Z:\work\sphinx\sphinx>mysql -P9306
Welcome to the MySQL monitor. Commands end with; or \g.
Your MySQL connection id is 1
Server version: 1.11-dev (r2691)
О блин… Я на конференции лично спрашивал, получил ответ что по подстроке не ищет в RT индексах. Потом немножко проверил сам и вроде тоже не смог по подстроке найти. В конце октября это было.
Это работало с момента появления RT индексов (ну, с выходом 1.10 т.е.) или недавно появилось?
Про триггера и вставку в MyISAM
Cтоит понимать, что транзакция на вставку в таблицу завершится тогда когда отработает триггер.
Триггер, разумеется, сумеет вставить в таблицу данные, и таблица будет залочена.
А вот паралельный запрос уже не сумеет вставить данные. Триггер будет ждать освобождения лока, а транзакция будет ждать триггер.
В общем при таком подходе теряется вся соль возможности паралельной вставки в InnoDB таблицу.
А в чем конкретно настолько продвинутее использовать основную таблицу в innodb, чтобы ради этого городить такой огород с зеркалами в myisam? Ну кроме транзакций, которые в небольших проектах и не особо нужны, атомарных операций myisam вполне достаточно. Ведь речь идет о небольшой проекте если правильно понял?
Приведенный пример несколько надуман. На деле эта самая таблица имеет куда больше полей. На проекте необходимо использование внешних ключей и транзакций, что недоступно в MyISAM
Отличная штука, она меня очень спасла. Использовал правда не Java версию, а зендовский модуль.
У меня была проблема в том, что надо было искать по 8 таблицам, что очень не удобно. Надо писать свой костыль. А Zend Lucene быстро подключил.
Спасибо, отличная статья!
Кармы не хватает, так бы однозначно плюсанул.
Коллеги, я бы хотел осветить одну очень интересную «плюшку» MySQL, а именно использования xPath/XML-деревьев, которая доступна с версии 5.1. Испытал и внедрил в СMS на Zend Framework, название пока говорить не буду, планируется opensource. Получается эдакий аналог MongoDB и сравнительно шустрая скорость выборки. Есть пример работы с этим чудом на PHP. Но вот друзья, кармы не хватает. Я, конечно, не клянчу в открытую, если поможете — опубликую в ближайшую неделю, т.к я очень досконально изучил этот вопрос. Если нет, то опубликую в блоге и в посте по теме запощу линк в комментарии.
Полнотекстовый поиск в InnoDB