Перейти к основному содержимому
Перейти к основному содержимому

Методы моделирования данных

Это Часть 3 руководства по миграции с PostgreSQL на ClickHouse. Этот контент можно считать вводным, с целью помочь пользователям развернуть начальную функциональную систему, которая соответствует лучшим практикам ClickHouse. Он избегает сложных тем и не приведет к полностью оптимизированной схеме; вместо этого он предоставляет надежную основу для пользователей, чтобы построить производственную систему и основать свое обучение.

Мы рекомендуем пользователям, мигрирующим с Postgres, прочитать руководство по моделированию данных в ClickHouse. Это руководство использует тот же набор данных Stack Overflow и исследует несколько подходов с использованием функций ClickHouse.

Партиции

Пользователи Postgres будут знакомы с концепцией партиционирования таблиц для повышения производительности и управляемости больших баз данных путем деления таблиц на более мелкие, более управляемые части, называемые партициями. Это партиционирование может быть достигнуто с использованием либо диапазона по указанной колонке (например, даты), определенных списков или через хеш по ключу. Это позволяет администраторам организовывать данные на основе определенных критериев, таких как диапазоны дат или географические местоположения. Партиционирование помогает в улучшении производительности запросов, позволяя более быстрый доступ к данным через отсечение партиций и более эффективное индексирование. Оно также помогает в таких задачах обслуживания, как резервное копирование и очистка данных, позволяя проводить операции с отдельными партициями, а не с таблицей целиком. Кроме того, партиционирование может значительно улучшить масштабируемость баз данных PostgreSQL, распределяя нагрузку по нескольким партициям.

В ClickHouse партиционирование указывается в таблице при ее первоначальном определении через оператор PARTITION BY. Этот оператор может содержать SQL-выражение по любым колонкам, результаты которого определяют, в какую партицию будет отправлен ряд.

Части данных логически ассоциируются с каждой партицией на диске и могут быть запрашиваемы изолированно. В следующем примере мы партиционируем таблицу posts по годам, используя выражение toYear(CreationDate). По мере вставки строк в ClickHouse это выражение будет оцениваться для каждой строки и маршрутизироваться в соответствующую партицию, если она существует (если строка является первой для года, партиция будет создана).

Применения партиций

Партиционирование в ClickHouse имеет аналогичные применения как в Postgres, но с некоторыми тонкими отличиями. Более специфично:

  • Управление данными - В ClickHouse пользователи должны в первую очередь рассматривать партиционирование как функцию управления данными, а не как технику оптимизации запросов. Разделяя данные логически на основании ключа, каждая партиция может управляться независимо, например, удаляться. Это позволяет пользователям перемещать партиции, а значит, и подмножества, между хранилищами эффективно по времени или истекать данные / эффективно удалять из кластера. В примере ниже мы удаляем посты с 2008 года.
  • Оптимизация запросов - Хотя партиции могут помочь с производительностью запросов, это сильно зависит от паттернов доступа. Если запросы нацелены только на несколько партиций (желательно одну), производительность может улучшиться. Это обычно полезно только в том случае, если ключ партиционирования не входит в первичный ключ и вы фильтруете по нему. Однако запросы, которым необходимо охватить множество партиций, могут работать медленнее, чем если бы партиционирование не использовалось (так как в результате партиционирования может быть больше частей). Польза от нацеливания на одну партицию будет еще менее выраженной до несуществия, если ключ партиционирования уже находится на ранней позиции в первичном ключе. Партиционирование также можно использовать для оптимизации запросов GROUP BY, если значения в каждой партиции уникальны. Однако, в целом, пользователи должны следить за тем, чтобы первичный ключ был оптимизирован, и рассматривать партиционирование как технику оптимизации запросов только в исключительных случаях, когда паттерны доступа затрагивают конкретное предсказуемое подмножество дня, например, партиционируя по дням, когда большинство запросов в последний день.

Рекомендации по партициям

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

Важно: Убедитесь, что ваше выражение ключа партиционирования не приводит к множеству с высокой кардинальностью, т.е. создание более 100 партиций следует избегать. Например, не следует партиционировать ваши данные по колонкам с высокой кардинальностью, таким как идентификаторы клиентов или имена. Вместо этого сделайте идентификатор клиента или имя первой колонкой в выражении ORDER BY.

Внутри ClickHouse создаются части для вставленных данных. По мере вставки дополнительных данных количество частей увеличивается. Чтобы предотвратить слишком высокое количество частей, что ухудшает производительность запросов (больше файлов для чтения), части объединяются в фоновом асинхронном процессе. Если количество частей превышает заранее сконфигурированный предел, ClickHouse выдаст исключение при вставке - как "слишком много частей". Это не должно происходить при нормальной работе и происходит только в случае неправильной настройки ClickHouse или неверного использования, например, при большом количестве маленьких вставок.

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

Материализованные представления против проекций

Postgres позволяет создавать несколько индексов на одной таблице, что позволяет оптимизировать различные паттерны доступа. Эта гибкость позволяет администраторам и разработчикам адаптировать производительность базы данных к конкретным запросам и операционным потребностям. Концепция проекций в ClickHouse, хоть и не полностью аналогична этому, позволяет пользователям указывать несколько операторов ORDER BY для таблицы.

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

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

Например, рассмотрим следующий запрос:

Этот запрос требует сканирования всех 90 миллионов строк (что, признаться, происходит быстро), так как UserId не является ключом упорядочивания. Ранее мы решили эту задачу с помощью материализованного представления, действующего как справочник для PostId. Ту же проблему можно решить с помощью проекции. Команда ниже добавляет проекцию для ORDER BY user_id.

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

Если проекция создана через ALTER, создание происходит асинхронно, когда команда MATERIALIZE PROJECTION выполняется. Пользователи могут подтвердить ход этой операции с помощью следующего запроса, дожидаясь is_done=1.

Если мы повторим вышеуказанный запрос, мы увидим, что производительность значительно улучшилась за счет дополнительных расходов на хранилище.

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

Когда использовать проекции

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

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

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

  • Проекции не позволяют использовать разные TTL для исходной таблицы и (скрытой) целевой таблицы, материализованные представления позволяют разные TTL.
  • Проекции в настоящее время не поддерживают optimize_read_in_order для (скрытой) целевой таблицы.
  • Легковесные обновления и удаления не поддерживаются для таблиц с проекциями.
  • Материализованные представления могут связываться: целевая таблица одного материализованного представления может быть исходной таблицей другого материализованного представления и так далее. Это невозможно с проекциями.
  • Проекции не поддерживают соединения; материализованные представления поддерживают.
  • Проекции не поддерживают фильтры (условие WHERE); материализованные представления поддерживают.

Мы рекомендуем использовать проекции, когда:

  • Требуется полная переупорядочиванию данных. Хотя выражение в проекции может, теоретически, использовать GROUP BY, материализованные представления более эффективны для поддержания агрегатов. Оптимизатор запросов также будет более склонен использовать проекции, которые используют простое переупорядочивание, т.е. SELECT * ORDER BY x. Пользователи могут выбрать подмножество колонок в этом выражении, чтобы уменьшить объем хранилища.
  • Пользователи комфортно принимают сопутствующее увеличение объема хранилища и накладные расходы на запись данных дважды. Проверьте влияние на скорость вставки и оцените накладные расходы на хранение.

Нажмите здесь для Части 4.