Поиск в огромной таблице - PullRequest
0 голосов
/ 01 мая 2011

Я получил таблицу с более чем 1 миллионом строк. В этой таблице представлена ​​информация о пользователе, например, имя пользователя, адрес электронной почты, пол, семейное положение и т. Д.

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

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

select from u where u.name ilike " ... "

Да, у меня есть индексы по некоторым полям. Я проверил, что они применяются с помощью команды объяснения анализа.

Как можно повысить поиск?

Мне что-то нравится в Lucene, это может помочь?

Мне интересно, как работает поиск в Facebook, у них миллиарды пользователей, и их поиск работает намного быстрее.

Ответы [ 4 ]

1 голос
/ 02 мая 2011

Что-то мне нравится в Lucene, это может помочь?

Да, это возможно. Я уверен, вам это понравится!

У меня была та же проблема: стол с круглыми сообщениями около 1,2 миллиона. Для поиска по этим сообщениям требуется несколько секунд. Для полнотекстового поиска в столбце «сообщение» требуется около 10 секунд.

На том же оборудовании сервера lucene возвращает результат примерно за 200-400 мс.

Это очень быстро.

Кэшированные результаты возвращаются за 5-10 мсек.

Lucene может подключиться к вашей базе данных SQL (например, mysql) - сканирует вашу базу данных и создает поисковый индекс.

Для поиска по этому индексу это зависит от типа приложения. В моем случае, моя PHP Webaplication использует solr для поиска внутри lucene. http://lucene.apache.org/solr/

1 голос
/ 01 мая 2011

Попробуйте использовать разбиение таблицы. В больших настольных сценариях может быть полезно разделить таблицу. Для PostgreSQL попробуйте здесь PostgreSQL Partitioning . Для быстрого масштабируемого поиска с высокой масштабируемостью иногда может быть полезно использовать NoSQL базу данных (как это делает Facebook).

1 голос
/ 02 мая 2011

Между этими тремя запросами существует большая разница:

a) SELECT * FROM u WHERE u.name LIKE "George%"

b) SELECT * FROM u WHERE u.name LIKE "%George"

c) SELECT * FROM u WHERE u.name LIKE "%George%"

a) Первый будет использовать индекс u.name (если он есть) и будет очень быстрым.


b) Второй не сможет использовать какой-либо индекс для u.name, но есть способы обойти это довольно легко.

Например, вы можете добавить другое поле nameReversedв таблице, где хранится REVERSE(name).С индексом в этом поле запрос будет переписан как (и будет таким же быстрым, как и первый):

b2) SELECT * FROM u WHERE u.nameReversed LIKE REVERSE("%George") 

c) Третий запрос представляет наибольшую сложность, поскольку ни один издва предыдущих индекса будут полезны, и запрос будет сканировать всю таблицу.Альтернативы:

Использование выделенного для решения таких проблем (поиск по «полнотекстовому поиску»), например, Sphinx.См. Этот вопрос о SO с более подробной информацией: Какие лучшие методы поиска для поиска записей

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

Если не по курсу, это не так, и у вас есть десяткитысячи или миллионы разных слов или поле содержит целые фразы, а затем решить проблему со многими вспомогательными таблицами, это все равно, что создать для себя инструмент полнотекстового поиска.Это хорошее упражнение, и вам не придется использовать Sphinx (или другой) помимо СУБД, но это не тривиально.

1 голос
/ 01 мая 2011

Посмотрите на Hibernate Search это использует Lucene, но намного проще в реализации.

Google или Facebook используют разные подходы. У них есть распределенные системы. Googles BigTable - это хорошее ключевое слово или концепция «Map and Reduce» (Apache Hadoop) - хорошая отправная точка для дальнейших исследований.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...