Clickhouse vs Elasticsearch vs Manticore Search в бенчмарке 10 миллионов логов Nginx

Введение

В этой статье мы рассмотрим еще один тест, добавленный на сайт https://db-benchmarks.com/ — 10+ миллионов стандартных HTTP логов, собранных Nginx на сайте электронной коммерции zanbil.ir.

Сбор данных

Мы нашли сбор данных на сайте https://www.kaggle.com/datasets/eliasdabbas/web-server-access-logs и сочли его очень интересным для проведения теста, поскольку набор данных представляет собой очень стандартный журнал http-доступа nginx. Вот пример:

54.36.149.41 - - [22/Jan/2019:03:56:14 +0330] "GET /filter/27|13%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,27|%DA%A9%D9%85%D8%AA%D8%B1%20%D8%A7%D8%B2%205%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,p53 HTTP/1.1" 200 30577 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" "-"
31.56.96.51 - - [22/Jan/2019:03:56:16 +0330] "GET /image/60844/productModel/200x200 HTTP/1.1" 200 5667 "https://www.zanbil.ir/m/filter/b113" "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36" "-"
31.56.96.51 - - [22/Jan/2019:03:56:16 +0330] "GET /image/61474/productModel/200x200 HTTP/1.1" 200 5379 "https://www.zanbil.ir/m/filter/b113" "Mozilla/5.0 (Linux; Android 6.0; ALE-L21 Build/HuaweiALE-L21) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36" "-"
40.77.167.129 - - [22/Jan/2019:03:56:17 +0330] "GET /image/14925/productModel/100x100 HTTP/1.1" 200 1696 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
91.99.72.15 - - [22/Jan/2019:03:56:17 +0330] "GET /product/31893/62100/%D8%B3%D8%B4%D9%88%D8%A7%D8%B1-%D8%AE%D8%A7%D9%86%DA%AF%DB%8C-%D9%BE%D8%B1%D9%86%D8%B3%D9%84%DB%8C-%D9%85%D8%AF%D9%84-PR257AT HTTP/1.1" 200 41483 "-" "Mozilla/5.0 (Windows NT 6.2; Win64; x64; rv:16.0)Gecko/16.0 Firefox/16.0" "-"
40.77.167.129 - - [22/Jan/2019:03:56:17 +0330] "GET /image/23488/productModel/150x150 HTTP/1.1" 200 2654 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
40.77.167.129 - - [22/Jan/2019:03:56:18 +0330] "GET /image/45437/productModel/150x150 HTTP/1.1" 200 3688 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
40.77.167.129 - - [22/Jan/2019:03:56:18 +0330] "GET /image/576/article/100x100 HTTP/1.1" 200 14776 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
66.249.66.194 - - [22/Jan/2019:03:56:18 +0330] "GET /filter/b41,b665,c150%7C%D8%A8%D8%AE%D8%A7%D8%B1%D9%BE%D8%B2,p56 HTTP/1.1" 200 34277 "-" "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" "-"
40.77.167.129 - - [22/Jan/2019:03:56:18 +0330] "GET /image/57710/productModel/100x100 HTTP/1.1" 200 1695 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
207.46.13.136 - - [22/Jan/2019:03:56:18 +0330] "GET /product/10214 HTTP/1.1" 200 39677 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
40.77.167.129 - - [22/Jan/2019:03:56:19 +0330] "GET /image/578/article/100x100 HTTP/1.1" 200 9831 "-" "Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" "-"
Вход в полноэкранный режим Выход из полноэкранного режима

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

После разбора фреймворком в журнале имеется 11 полей:

  • 7 строковых полей
  • 4 целочисленных поля

Весь список полей и их типы данных:

"properties": {
  "remote_addr": {"type": "text"},
  "remote_user": {"type": "text"},
  "runtime": {"type": "long"},
  "time_local": {"type": "long"},
  "request_type": {"type": "text"},
  "request_path": {
    "type": "text",
    "fields": {
      "raw": {
        "type": "keyword"
      }
    }
  },
  "request_protocol": {"type": "text"},
  "status": {"type": "long"},
  "size": {"type": "long"},
  "referer": {"type": "text"},
  "usearagent": {"type": "text"}
}
Вход в полноэкранный режим Выход из полноэкранного режима

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

Базы данных

На данный момент мы сделали этот тест доступным для 3 баз данных:

  • Clickhouse — мощная OLAP база данных,
  • Elasticsearch — «поисково-аналитический движок» общего назначения,
  • Manticore Search — «база данных для поиска», альтернатива Elasticsearch.

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

  • Clickhouse: никаких настроек, просто CREATE TABLE ... ENGINE = MergeTree() ORDER BY id и стандартный докер-образ clickhouse-server.
  • Elasticsearch: мы тестируем в двух режимах:

    • без настройки вообще, что, вероятно, и делает большинство пользователей
    • с количеством шардов, равным количеству ядер CPU на сервере, чтобы Elasticsearch мог использовать CPU более эффективно для снижения времени отклика, поскольку, как сказано в официальном руководстве Elasticsearch, «каждый шард выполняет поиск на одном потоке CPU». Размер набора данных составляет всего 3,5 ГБ, поэтому неясно, нужно ли это или нет, но мы тестируем именно это.
  • Manticore Search — никаких настроек, просто обычный индекс, созданный из CSV.

    • Мы тестируем хранение Manticore по умолчанию в виде строк
    • и колоночное хранение, поскольку Elasticsearch и Clickhouse не предоставляют хранилищ, ориентированных на строки, и, возможно, будет более справедливо сравнить с Manticore, работающим в этом режиме.

О кэшах

Мы также настроили базы данных так, чтобы они не использовали никаких внутренних кэшей. Почему это важно:

  1. В этом бенчмарке мы проводим точное измерение задержки, чтобы выяснить, какое время отклика может ожидать пользователь, если он выполнит один из тестируемых запросов в случайный момент, а не после многократного выполнения одного и того же запроса.
  2. Любой кэш — это короткий путь к низкой задержке. Как написано в Википедии, «кэш хранит данные, чтобы будущие запросы на эти данные обслуживались быстрее». Но кэши бывают разные, их можно разделить на 2 основные группы:

    • 👌 те, которые просто кэшируют необработанные данные, хранящиеся на диске. Например, многие базы данных используют mmap() для отображения данных, хранящихся на диске, в память, легкого доступа к ним и предоставления операционной системе заботиться об остальном (чтение с диска, когда есть свободная память, удаление из памяти, когда она нужна для чего-то более важного и т.д.). Это нормально с точки зрения тестирования производительности, потому что мы позволяем каждой базе данных использовать преимущества использования страничного кэша ОС (или ее внутреннего аналогичного кэша, который просто считывает данные с диска) Именно это мы и делаем в этом бенчмарке.
    • ❗ те, которые используются для сохранения результатов предыдущих вычислений. И это хорошо во многих случаях, но с точки зрения этого бенчмарка позволить базе данных включить такой кэш — плохая идея, потому что:
      • это нарушает правильное измерение: вместо измерения времени вычисления вы начинаете измерять, сколько времени требуется, чтобы найти значение по ключу в памяти. Это не то, что мы хотим сделать в данном тесте (но это интересно в целом, и мы, возможно, сделаем это в будущем и опубликуем статью «Бенчмарк кэшей»).
      • Даже если они сохраняют не полный результат конкретного запроса, а результаты его подвычислений, это нехорошо, потому что нарушает идею теста — «какое время отклика может ожидать пользователь, если он выполнит один из тестируемых запросов в случайный момент времени».
      • Некоторые базы данных имеют такой кэш (он обычно называется «кэш запросов»), другие нет, поэтому если мы не отключим внутренний кэш базы данных, мы дадим несправедливое преимущество тем, у кого он есть.

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

Что именно мы делаем для достижения этой цели:

  • Clickhouse:

  • Elasticsearch:

  • Manticore Search (в конфигурационном файле):

    • qcache_max_bytes = 0
    • docstore_cache_size = 0
  • Операционная система:

    • мы делаем echo 3 > /proc/sys/vm/drop_caches; sync перед каждым НОВЫМ запросом (НЕ перед каждой попыткой). Т.е. для каждого нового запроса мы:
    • останавливаем базу данных
    • сбрасываем кэш ОС
    • запускаем её снова
    • делаем самый первый холодный запрос и измеряем его время
    • и делаем еще десятки попыток (до 100 или пока коэффициент вариации не станет достаточно низким, чтобы считать результаты тестирования качественными).

Запросы

Запросы в основном аналитические, которые выполняют фильтрацию, сортировку и группировку, но мы также включили один полнотекстовый запрос, который ищет в URL запроса:

[
"select avg(size) avg_size, status from logs10m group by status order by avg_size desc limit 20",
{
  "manticoresearch": "select count(*) as cnt, avg(runtime), avg(size) from logs10m where match('@request_path settings logo') order by cnt desc limit 20",
  "elasticsearch": "select count(*) as cnt, avg(runtime), avg(size) from logs10m where query('request_path settings logo') order by cnt desc limit 20",
  "clickhouse": "select count(*) as cnt, avg(runtime), avg(size) from logs10m where (match(request_path, '(?i)(\W|\A)settings\Wlogo(\W|\z)') or match(request_path, '(?i)(\W|\A)logo\Wsettings(\W|\z)')) limit 20 FORMAT JSON"
},
"select count(*) from logs10m",
"select count(*), avg(runtime) from logs10m group by status limit 20",
"select count(distinct request_path) cnt_distinct, status from logs10m group by status order by cnt_distinct desc limit 20",
"select min(size) min_size, status from logs10m group by status order by min_size desc, status desc limit 20",
"select request_path, runtime, status, size from logs10m where size > 0 order by runtime desc, size asc limit 20",
"select request_path, runtime, status, size, time_local from logs10m order by runtime desc, size desc, time_local desc limit 20",
"select status, count(*) from logs10m group by status order by count(*) desc limit 20",
"select status, sum(runtime) from logs10m group by status order by count(*) desc limit 20",
"select count(*) as cnt, request_path, avg(runtime), avg(size) from logs10m group by request_path order by cnt desc limit 20",
"select request_path, count(*), avg(runtime) runtime_avg, avg(size) from logs10m group by request_path order by runtime_avg desc limit 20"
]
Войти в полноэкранный режим Выйти из полноэкранного режима

Результаты

Вы можете найти все результаты на странице результатов, выбрав «Тест: logs10m».

Помните, что единственной метрикой высокого качества является «Fast avg», так как она гарантирует низкий коэффициент вариации и высокое количество запросов, проведенных по каждому запросу. Две другие («Fastest» и «Slowest») не дают никаких гарантий:

Slowest — это результат одной попытки, в большинстве случаев самый первый холодный запрос. Несмотря на то, что мы очищаем кэш ОС перед каждым холодным запросом, его нельзя считать стабильным. Поэтому его можно использовать только в информационных целях (несмотря на то, что многие авторы бенчмарков публикуют такие результаты без каких-либо оговорок).
Fastest — только самый быстрый результат, в большинстве случаев он должен быть похож на метрику «Fast avg», но может быть более изменчив от прогона к прогону.

Помните, что тесты, включая результаты, на 100% прозрачны, как и все в этом проекте, поэтому:

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

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

3 конкурента без тюнинга одновременно

К сожалению, Elasticsearch прервал выполнение 2 запросов, поэтому они были исключены из подсчета итоговых результатов.

Elasticsearch без настройки против Manticore Search (хранение по умолчанию в виде строк)

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

Elasticsearch без настройки против настроенного

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

Elasticsearch с настройкой против Manticore Search (хранение рядов по умолчанию)

К сожалению, Elasticsearch прервал выполнение 2 запросов, поэтому они были исключены из подсчета итоговых результатов.

Elasticsearch tuned в сравнении с Manticore Search (колоночное хранилище)

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

Clickhouse vs Manticore Search (колоночное хранение)

Manticore Search row-wise vs columnar

Отказ от ответственности

Автор этого теста и тестовой схемы является членом основной команды Manticore Search, и тест изначально был сделан для сравнения Manticore Search с Elasticsearch, но, как показано выше и можно проверить в открытом исходном коде и при выполнении того же теста самостоятельно, Manticore Search не получил никакого несправедливого преимущества, поэтому тест можно считать непредвзятым. Тем не менее, если в тесте что-то упущено или неправильно (т.е. не объективно), не стесняйтесь сделать запрос на исправление или проблему на Github. Ваше мнение будет оценено по достоинству! Спасибо, что потратили свое время на прочтение этой статьи!

Оцените статью
Procodings.ru
Добавить комментарий