Колоночные базы данных невероятно быстры. Вот почему.

BBetter Stack
Computing/Software

Transcript

00:00:00Хотя я безумно люблю Postgres, он идеален далеко не во всём. Существует другой тип
00:00:04баз данных — колоночные базы данных, которые могут выполнять определённые запросы до 40 раз быстрее. Эти
00:00:10базы данных работают, сохраняя столбцы вместе, а не строки, что дает огромные преимущества
00:00:15для определённых сценариев использования, таких как аналитические платформы. Конечно, за всё приходится платить,
00:00:20но сегодня мы подробно рассмотрим, что такое колоночные базы данных, и сравним несколько запросов
00:00:25с Postgres, чтобы увидеть плюсы и минусы. Мы сравним Postgres с ClickHouse и DuckDB,
00:00:31так что оставайтесь с нами, и к концу вы получите четкое представление о колоночных базах данных
00:00:36и о том, когда какую технологию использовать.
00:00:43Итак, в начале я сказал, что некоторые запросы можно выполнять в 40 раз быстрее, и это правда. Если взять
00:00:49таблицу базы данных — здесь я загрузил сто миллионов строк — и запустить запрос с группировкой в
00:00:55Postgres, то на его выполнение уходит примерно 9,7 секунды, потому что мы агрегируем выручку из каждой
00:01:00каждая строка, если мы выполним тот же запрос по тому же набору данных с использованием столбцовой базы данных, и это
00:01:06используя буквально тот же самый SQL (и ClickHouse, и DuckDB имеют синтаксис SQL, похожий на Postgres, так что вам
00:01:13всё будет знакомо) — ClickHouse справляется за 0,28 секунды, а DuckDB за 0,24 секунды. Это более чем в 40 раз быстрее!
00:01:22Как это возможно? Кажется невероятным, верно? Те же 100 миллионов строк обрабатываются всего за 0,24 секунды.
00:01:30Просто колоночные базы данных выполняют на порядки меньше работы для получения тех же результатов.
00:01:36Давайте посмотрим на другой запрос в действии. И небольшая ремарка, ребята: мы постоянно выпускаем контент об ИИ и технологиях,
00:01:42так что если вам это нравится, почему бы не подписаться на Better Stack? На этот раз мы подсчитываем количество
00:01:47событий между двумя метками времени, где код страны равен gb. В нашем случае мы смотрим на данные за
00:01:53март. Результаты: Postgres — 5,9 секунды, ClickHouse — 0,06 секунды и DuckDB — 0,03 секунды. Март содержит
00:02:02около 13 процентов всех событий, поэтому Postgres по-прежнему приходится просматривать миллионы строк. Мы могли бы
00:02:09добавить сюда агрессивное индексирование, но это не приблизит нас к ClickHouse и DuckDB. Так почему же
00:02:15колоночные хранилища здесь намного быстрее? Что ж, ClickHouse вообще не индексирует отдельные строки. Когда вы создаете
00:02:20таблицу, вы задаете ей ключ сортировки, и данные сортируются по метке времени, после чего отсортированные данные разбиваются на блоки по
00:02:32и сохраняется только информация о первой метке времени в каждом из них. Для 100 миллионов строк это около 12 000 записей,
00:02:39и это достаточно мало, чтобы поместиться в памяти. Поэтому, когда мы запрашиваем март, система быстро ищет среди этих
00:02:44записей, находит блоки, которые могут содержать март, и считывает только их. В нашем случае это 1633 блока из
00:02:5212 208, а всё остальное на диске пропускается. DuckDB делает нечто похожее, поскольку хранит минимальное
00:03:00и максимальное значения для каждого чанка столбца. Таким образом, мы можем посмотреть на чанк, увидеть, что метки времени идут с января по
00:03:06февраль, и полностью пропустить его, даже не читая. Добавьте к этому трюк из прошлого примера, где открываются
00:03:10только нужные столбцы, и вы получаете 0,03 секунды. Но всё кардинально меняется, когда вам нужно
00:03:17выбрать одну единственную строку по ID. Этот простой запрос многое проясняет: Postgres тратит две миллисекунды, ClickHouse — 168
00:03:26миллисекунд, а DuckDB, что интересно, укладывается всё в те же две миллисекунды. У Postgres есть индекс на основе B-дерева для
00:03:32поля ID, поэтому он спускается по дереву, попадает на ту единственную страницу, где хранится строка, и всё готово всего за
00:03:37две миллисекунды. Но с ClickHouse у нас проблемы: его единственный индекс — это ключ сортировки, а эта таблица
00:03:43отсортирована сначала по метке времени, а во вторую очередь — по ID. Поэтому, когда мы запрашиваем конкретный ID, база понятия не имеет, в каком блоке
00:03:51он находится, и в итоге проверяет каждый из 12 208 блоков. И даже найдя строку, ей всё равно
00:03:57приходится открывать все восемь файлов столбцов и собирать строку заново, что является огромным объемом работы для столь
00:04:03простого запроса. Так как же DuckDB сходит это с рук? Ей просто повезло с нашими данными: ID вставлялись по
00:04:09порядку, поэтому минимум и максимум в каждом чанке аккуратно совпадают с ID, и DuckDB может перейти прямо к нужному
00:04:16чанку. Если бы ID были перемешаны, ей пришлось бы сканировать весь столбец, точно так же как ClickHouse. Давайте теперь посмотрим
00:04:21на обновление строки. У нас есть один запрос для Postgres и DuckDB и немного другая версия для
00:04:26ClickHouse. Postgres справился за 5 миллисекунд, ClickHouse — за 5,8 секунды, а DuckDB — снова всего за десятки
00:04:34миллисекунд. Postgres просто перезаписывает одну строку и обновляет одну запись в индексе. В ClickHouse файлы данных
00:04:40неизменяемы, они никогда не редактируются на месте, поэтому для изменения одного значения выручки приходится перезаписывать
00:04:46весь файл столбца выручки для этого чанка таблицы. ClickHouse даже заставляет писать это как операцию
00:04:51ALTER TABLE, поскольку воспринимает это как мутацию всей таблицы. Существует более легкое обновление в
00:04:56бета-версии, но оно предназначено только для небольшого числа строк — примерно до 10 процентов таблицы максимум. DuckDB занимает промежуточное
00:05:03положение между ними, поскольку её файл может изменяться на месте, поэтому обновление одной строки занимает несколько десятков
00:05:08миллисекунд. И наконец, давайте подсчитаем количество уникальных пользователей в нашей таблице (снова с небольшой
00:05:14модификацией запроса для ClickHouse). Результаты таковы: Postgres — 38,4 секунды, ClickHouse — 0,78 секунды,
00:05:22а DuckDB — меньше секунды. Опять же, Postgres страдает: агрегация по всей столь огромной таблице
00:05:28просто требует колоссального объема работы. Теперь, вы, вероятно, захотите использовать колоночные базы данных для таких задач, как аналитика,
00:05:34где агрегирование данных по различным столбцам является обычной задачей. Здесь мы рассмотрели два варианта: ClickHouse
00:05:41представляет собой хостинговый сервер с открытым исходным кодом, доступный на большинстве основных платформ. Чтобы запустить его локально, вам нужно запустить
00:05:47сервер ClickHouse на своем компьютере, что ближе к тому, как работает Postgres. DuckDB, однако, больше похожа на SQLite:
00:05:54это библиотека, которая работает внутри собственного процесса, а вся база данных живет в одном файле на диске. Из-за этого
00:06:00файл может быть заблокирован во время выполнения обновления, что сводит на нет параллелизм. Обе базы являются колоночными,
00:06:06но используют совершенно разные подходы. Так что выбор базы данных в итоге сводится к гораздо большему,
00:06:12чем я могу предположить здесь. Дело не только в чистой скорости выполнения запросов при тестировании на локальном компьютере,
00:06:17но и в масштабируемости, избыточности и расширяемости. Конечно, у Postgres есть богатая экосистема плагинов для
00:06:24расширения функционала самыми разными способами, о чем вы можете узнать из этого видео.

Key Takeaway

Колоночные базы данных обеспечивают колоссальный прирост скорости до 40 раз при аналитических запросах за счет сохранения столбцов вместе, однако уступают традиционным строковым СУБД в точечных обновлениях и поиске единичных записей.

Highlights

  • Колоночные базы данных, такие как ClickHouse и DuckDB, выполняют запросы с группировкой по 100 миллионам строк более чем в 40 раз быстрее по сравнению с Postgres.

  • ClickHouse и DuckDB обрабатывают запрос по миллионам строк за доли секунды благодаря хранению данных в виде столбцов и механизмам пропуска ненужных блоков.

  • Postgres справляется с точечным поиском по единственному идентификатору за 2 миллисекунды, в то время как ClickHouse тратит на это 168 миллисекунд из-за необходимости сканировать все блоки.

  • Изменение отдельной строки в ClickHouse занимает 5,8 секунды из-за неизменяемости файлов данных, требующей перезаписи целых колоночных блоков.

  • DuckDB функционирует как встроенная библиотека в одном файле на диске, в отличие от ClickHouse, который работает как сервер с открытым исходным кодом.

Timeline

Сравнение производительности на аналитических запросах с группировкой

  • Колоночные базы данных обрабатывают определенные типы запросов в 40 раз быстрее благодаря хранению данных по столбцам.
  • Запрос с группировкой по 100 миллионам строк выполняется в Postgres за 9,7 секунды.
  • ClickHouse выполняет аналогичный запрос по тому же набору данных за 0,28 секунды.
  • DuckDB завершает обработку того же SQL-запроса за 0,24 секунды.

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

Принцип работы фильтрации и индексации в колоночных базах

  • Запрос по временным меткам для 13 процентов от 100 миллионов строк выполняется в Postgres за 5,9 секунды.
  • ClickHouse завершает тот же временной запрос за 0,06 секунды без индексации отдельных строк.
  • DuckDB обрабатывает фильтрацию по диапазонам времени за 0,03 секунды.
  • ClickHouse разбивает отсортированные по ключу данные на блоки и сохраняет информацию только о первой метке времени в каждом блоке.

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

Производительность при точечном поиске по идентификатору

  • Postgres находит единственную строку по полю ID за 2 миллисекунды с помощью B-дерева.
  • ClickHouse тратит на поиск одной строки по ID 168 миллисекунд.
  • DuckDB находит запись за 2 миллисекунды за счет совпадения порядка вставки данных с чанками.

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

Операции обновления записей и мутации данных

  • Postgres обновляет одну строку за 5 миллисекунд.
  • ClickHouse тратит на аналогичное обновление 5,8 секунды.
  • DuckDB выполняет операцию обновления за десятки миллисекунд.

Файлы данных в ClickHouse неизменяемы, поэтому изменение даже одного значения выручки требует перезаписи целого файла столбца для конкретного чанка через операцию ALTER TABLE. DuckDB допускает изменение файлов на месте для определенных сценариев, а Postgres перезаписывает отдельную запись в индексе.

Архитектурные различия и выбор технологии для проектов

  • Подсчет уникальных пользователей на всей таблице занимает у Postgres 38,4 секунды, у ClickHouse 0,78 секунды, а у DuckDB меньше секунды.
  • ClickHouse работает как хостинговый сервер с открытым исходным кодом.
  • DuckDB функционирует как библиотека внутри собственного процесса с единственным файлом на диске.

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

Community Posts

No posts yet. Be the first to write about this video!

Write about this video