Почему Solr намного быстрее, чем Postgres?



Я недавно переключился с Postgres на Solr и увидел ~50x ускорение в наших запросах. Запросы, которые мы выполняем, включают в себя несколько диапазонов, и наши данные-это списки транспортных средств. Например: "найти все автомобили с пробегом


Я создал индексы по всем соответствующим столбцам в Postgres, поэтому это должно быть довольно справедливое сравнение. Глядя на план запроса в Postgres, хотя он все еще просто использовал один индекс, а затем сканировал (я предполагаю потому что он не мог использовать все различные индексы).



насколько я понимаю, Postgres и Solr используют смутно похожие структуры данных (B-деревья), и они оба кэшируют данные в памяти. Поэтому мне интересно, откуда такая большая разница в производительности.



какие различия в архитектуре могли бы объяснить это?

740   5  

5 ответов:

во-первых, Solr не использует B-деревья. Индекс Lucene (базовая библиотека, используемая Solr) состоит из индекса только для чтения сегментов. Для каждого сегмента Lucene поддерживает словарь терминов, который состоит из списка терминов, которые появляются в сегменте, лексикографически отсортированных. Поиск термина в этом словаре терминов производится с использованием двоичного поиска, поэтому стоимость поиска одного термина составляет O(log(t)) где t-число членов. Наоборот, используя индекс стандартной СУБД затраты O(log(d)) где D-количество документов. Когда многие документы имеют одинаковое значение для некоторого поля, это может быть большой выигрыш.

кроме того, Lucene committer Уве Шиндлер добавил поддержку очень performant запросы числового диапазона несколько лет назад. Для каждого значения числовое поле, Lucene хранит несколько значений с различной точностью. Это позволяет Lucene выполнять запросы диапазона очень эффективно. Поскольку ваш прецедент, похоже, использует числовой диапазон запросов много, это может объяснить, почему Solr настолько быстрее. (Для получения дополнительной информации, прочитайте javadocs, которые очень интересны и дают ссылки на соответствующие научные работы.)

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

вы не очень много говорили о том, что вы сделали, чтобы настроить свой экземпляр PostgreSQL или ваши запросы. Нет ничего необычного в том, что 50-кратное ускорение запроса PostgreSQL достигается путем настройки и/или повторной обработки вашего запроса в формате, который лучше оптимизирует.

только на этой неделе был отчет на работе, который кто-то написал с использованием Java и нескольких запросов таким образом, который, основываясь на том, как далеко он добрался за четыре часа, займет примерно месяц. (Он должен был ударить пять различные таблицы, каждая с сотнями миллионов строк.) Я переписал его с помощью нескольких CTE и оконной функции, чтобы он работал менее чем за десять минут и генерировал желаемые результаты прямо из запроса. Это 4400x скорость вверх.

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

Я включаю короткий пример того, как текстовый поиск по нескольким критериям может быть выполнен в PostgreSQL, и как несколько небольших настроек могут сделать большую разницу в производительности. Чтобы держать его быстро и просто я просто бегу Война и мир в текстовой форме в тестовую базу данных, причем каждый "документ" представляет собой одну текстовую строку. Подобные методы могут быть использованы для произвольных полей с помощью hstore тип или JSON столбцы, если данные должны быть слабо определены. Там, где есть отдельные столбцы со своими собственными индексами, преимущества использования индексов, как правило, намного больше.

-- Create the table.
-- In reality, I would probably make tsv NOT NULL,
-- but I'm keeping the example simple...
CREATE TABLE war_and_peace
  (
    lineno serial PRIMARY KEY,
    linetext text NOT NULL,
    tsv tsvector
  );

-- Load from downloaded data into database.
COPY war_and_peace (linetext)
  FROM '/home/kgrittn/Downloads/war-and-peace.txt';

-- "Digest" data to lexemes.
UPDATE war_and_peace
  SET tsv = to_tsvector('english', linetext);

-- Index the lexemes using GiST.
-- To use GIN just replace "gist" below with "gin".
CREATE INDEX war_and_peace_tsv
  ON war_and_peace
  USING gist (tsv);

-- Make sure the database has statistics.
VACUUM ANALYZE war_and_peace;

после настройки для индексирования я показываю несколько поисков с подсчетом строк и таймингов с обоими типами индексов:

-- Find lines with "gentlemen".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'gentlemen');

84 строки, gist: 2.006 ms, gin: 0.194 ms

-- Find lines with "ladies".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'ladies');

184 строк, суть: 3.549 МС, Джин: 0.328 МС

-- Find lines with "ladies" and "gentlemen".
EXPLAIN ANALYZE
SELECT * FROM war_and_peace
  WHERE tsv @@ to_tsquery('english', 'ladies & gentlemen');

1 строка, суть: 0.971 МС, Джин: 0.104 МС

теперь, поскольку индекс GIN был примерно в 10 раз быстрее, чем индекс GiST, вы можете задаться вопросом, почему кто-то будет использовать GiST для индексирования текстовых данных. Ответ заключается в том, что GiST, как правило, быстрее поддерживать. Поэтому, если ваши текстовые данные сильно изменчивы, индекс GiST может выиграть при общей загрузке, в то время как индекс GIN выиграет, если вас интересует только время поиска или чтение-в основном рабочая загрузка.

без индекса вышеуказанные запросы занимают от 17.943 мс до 23.397 мс, так как они должны сканировать всю таблицу и проверять соответствие в каждой строке.

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

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

с медленным запросом PostgreSQL, если вы показываете структуру таблицы (включая индексы), запрос проблемы и вывод от запуска EXPLAIN ANALYZE вашего запроса, кто-то может почти всегда определить проблему и предложить, как заставить его работать быстрее.


обновление (Dec 9 ' 16)

Я не упомянул, что я используется для получения предыдущих таймингов, но на основе даты это, вероятно, был бы основной релиз 9.2. Я просто наткнулся на этот старый поток и попробовал его снова на том же оборудовании, используя версию 9.6.1, чтобы увидеть, помогает ли какая-либо промежуточная настройка производительности в этом примере. Запросы только для одного аргумента только увеличились в производительности примерно на 2%, но поиск строк с обоими "дамами"и "джентльмены" примерно удвоились в скорости до 0,053 МС (т. е. 53 микросекунды), когда используя индекс Джина (перевернутый).

Это самое большое различие заключается в том, что индекс Lucene/Solr похож на базу данных с одной таблицей без поддержки реляционных запросов (соединений). Помните, что индекс обычно существует только для поддержки поиска и не является основным источником данных. Таким образом, ваша база данных может быть в "третьей нормальной форме", но индекс будет полностью де-нормализован и содержать в основном только данные, необходимые для поиска.

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

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

Solr предназначен в первую очередь для поиска данных, а не для хранения. Это позволяет ему отказаться от большей части функций, требуемых от RDMS. Так он (или, скорее,lucene) концентрируется на чисто индексирования данных.

Как вы, несомненно, обнаружили, Solr позволяет осуществлять поиск и извлечение данных из его индекса. Это последняя (необязательная) возможность, которая приводит к естественному вопросу... "Могу ли я использовать Solr в качестве базы данных?"

ответ a квалифицированный да, и я отсылаю вас к следующему:

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

читайте этой и этой.

Solr (Lucene) создает инвертированный индекс где извлечение данных становится довольно быстро. Я читать что PostgreSQL также имеет аналогичный объект, но не уверен, что вы использовали это.

различия в производительности, которые вы наблюдали, также могут быть отнесены к "что ищется ?", "каковы запросы пользователей ?"

Comments

    Ничего не найдено.