Как реализовать более быстрый API поиска по мере ввода (SAYT) в приложении Rails 3 - PullRequest
9 голосов
/ 24 февраля 2012

В моей базе данных mysql миллионы записей.Я реализовал нормальный API REST для приложения iPhone в Rails 3, но функция SAYT работает очень медленно.Поиск в базе данных и возврат результатов занимает много времени.Как я могу улучшить производительность?

Я проиндексировал свои таблицы.На какие аспекты я должен обращать больше внимания, например, на настройку MySQL, или я должен использовать rails sphinx или sunspot?Поможет ли это? Пожалуйста, помогите мне со всеми вашими советами экспертов.

Ответы [ 6 ]

2 голосов
/ 14 марта 2012

Я согласен с общим ответом: используйте поисковик, такой как Sphinx (и ограничьте количество возвращаемых результатов); они предназначены для того, чтобы делать именно то, что вы хотите.

Однако, несмотря на то, что миллионы записей могут звучать как много, вы должны сначала определить, что занимает много времени. Я очень люблю Sphinx и ThinkingSphinx - они принимают довольно сложный процесс и делают его довольно простым и легким. Но, в конце концов, поисковая система - это еще одна система для управления, настройки, обучения и знания. Если вам не нужно идти туда, проще не делать, верно?

Это может быть запрос, это может быть время, потраченное на возврат данных (limit ваш друг!). Или может случиться так, что вы получаете сотни запросов в секунду, возможно, потому что задержка при автозаполнении слишком короткая - если поиск происходит по каждому символу, быстрые машинистки или несколько пользователей могут легко перебежать сервер с запросами, которые не предоставляют утилиты для пользователя.

Посмотрите журналы Rails и посмотрите, что на самом деле происходит. Если это простая проблема производительности запросов, выполнение сложного полнотекстового поиска, тогда, да, это будет медленно, и Сфинкс будет стоить усилий. В вашей базе данных есть инструмент explain, который после некоторой работы поможет вам понять, что делает база данных, чтобы получить результат. Нередко индекс не привыкает.

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

1 голос
/ 13 марта 2012

Для быстрого поиска миллионов записей вы, вероятно, захотите использовать структуру данных типа trie. http://en.wikipedia.org/wiki/Trie содержит пример кода ruby, если вам нужна помощь.

Немного упростив, trie - это высокоэффективный метод хранения, позволяющий отследить, какие дети принадлежат к какому начальному списку символов.

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

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

1 голос
/ 01 марта 2012

Я бы также порекомендовал использовать систему полнотекстового поиска, такую ​​как Sphinx.

Есть хороший скринкаст о том, как использовать Sphinx и рельсы с гемомinking_sphinx:

Railscast think_sphinx gem

С этим драгоценным камнем вы также можете повлиять на результат поиска относительно важности, например, добавив вес поля:

Документация Thinking Sphinx

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

Получайте удовольствие

1 голос
/ 25 февраля 2012

Я не уверен, что вы имеете в виду, добавляя более быстрый поиск, но полезно ограничить результаты поиска до 100, поскольку это касается удобства использования. Не многие пользователи просматривают 100 записей для поиска.

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

Таким образом, это поможет вам определить первую сотню записей и наиболее точный поиск.

Существует много алгоритмов поиска, так как Map Reduce также работает одновременно. Я не думаю, что технология вашего мобильного устройства может справиться с уменьшением карты.

0 голосов
/ 14 марта 2012

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

0 голосов
/ 11 марта 2012

В зависимости от того, какой запрос вы делаете, LIKE запросов, которые совпадают в начале столбца, могут использовать индексы (в Postgres я точно знаю, что они есть; в MySQL я не уверен).

Итак,

Widget.where('name LIKE ?', "#{search_term}%").all

будет использовать индекс базы данных (по крайней мере, в Postgres), а

Widget.where('name LIKE ?', "%#{search_term}%").all

- нет.Обратите внимание на % в начале поискового запроса.Ваш пробег также может варьироваться в зависимости от ILIKE (без учета регистра), против LIKE (с учетом регистра) условий.Прочитайте документы базы данных.Это может быть самый низко висящий фрукт.

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

...