ClickHouse

Типы данных ClickHouse: String, UInt, DateTime и JSON

Типы данных в ClickHouse напрямую влияют на скорость чтения, размер таблицы и удобство запросов. В аналитической базе нельзя бездумно хранить все как String: дата должна быть датой, деньги — Decimal, небольшие справочники — LowCardinality, а Nullable стоит включать только там, где действительно нужен отдельный смысл NULL

Почему типы так важны

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

Числовые типы

Тип Когда использовать
UInt8, UInt16, UInt32, UInt64 Счетчики, id без отрицательных значений, статусы
Int8Int64 Числа, где возможны отрицательные значения
Float32, Float64 Измерения, метрики, приблизительные значения
Decimal Деньги и точные десятичные значения

Не берите максимальный тип «на всякий случай». Если статус помещается в UInt8, не нужен UInt64. Чем точнее тип, тем лучше сжатие и меньше чтение

Строки и LowCardinality

String подходит для произвольных строк: URL, поисковый запрос, сообщение, внешний id. Но если значений немного и они повторяются, используйте LowCardinality(String). Примеры: страна, тип события, тариф, источник, статус

event_type LowCardinality(String),
country LowCardinality(String),
plan LowCardinality(String)

LowCardinality хранит словарь значений и компактные ссылки на него. Это особенно полезно для измерений в аналитике

Когда можно оставить поле строкой?

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

Дата и время

  • Date — день без времени. Подходит для партиций, отчетов по дням, календарных фильтров.
  • Date32 — расширенный диапазон дат.
  • DateTime — дата и время с точностью до секунды.
  • DateTime64 — дата и время с долями секунды, например для логов и метрик.
event_date Date,
event_time DateTime,
request_time DateTime64(3)

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

Nullable: включать осторожно

Nullable(T) нужен, когда отсутствие значения отличается от нуля, пустой строки или значения по умолчанию. Но Nullable добавляет служебные данные и усложняет некоторые операции. Если поле всегда известно или можно задать нормальное значение по умолчанию, Nullable не нужен

-- Уместно: дата первого платежа может быть неизвестна
first_payment_at Nullable(DateTime)
-- Часто не нужно: статус лучше хранить явным значением
status LowCardinality(String) DEFAULT 'unknown'

JSON, Array, Tuple и Nested

ClickHouse умеет работать с полуструктурированными данными, но выбор зависит от задачи. Если структура стабильная, лучше использовать обычные колонки. Если ключи действительно меняются от события к событию, можно рассмотреть тип JSON. Если у записи есть список тегов, подойдет Array(String)

tags Array(String),
payload JSON,
position Tuple(Float64, Float64)

Не путайте JSON как формат загрузки и JSON как тип колонки. Можно загружать строки в формате JSONEachRow, но это не значит, что каждая колонка должна быть типа JSON

JSON и Array в ClickHouse

Когда JSON и Array лучше вынести в отдельную тему?

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

Что проверить перед созданием таблицы?

Посмотрите не только на пример данных, но и на будущие запросы: какие поля участвуют в WHERE, GROUP BY, JOIN и ORDER BY. Подробный сценарий создания схемы вынесен в инструкцию как создать таблицу ClickHouse

Пример хорошей схемы событий

CREATE TABLE demo.pageviews
(
    event_date Date,
    event_time DateTime64(3),
    user_id UInt64,
    url String,
    source LowCardinality(String),
    status UInt16,
    duration_ms UInt32,
    revenue Decimal(12, 2),
    tags Array(String),
    payload JSON
)
ENGINE = MergeTree
ORDER BY (event_date, source, user_id);

Как посмотреть типы в таблице

DESCRIBE TABLE numbers(1);

В официальном Playground команда возвращает колонку number типа UInt64. Для своей схемы замените numbers(1) на имя таблицы

Шпаргалка выбора типов

Данные Рекомендуемый тип
id пользователя UInt64
тип события LowCardinality(String)
день отчета Date
время события DateTime или DateTime64
стоимость заказа Decimal(12, 2)
HTTP-статус UInt16
теги Array(String)
динамические свойства события JSON, если структура реально меняется

Как мигрировать от сырых строк к нормальным типам

В реальных проектах данные часто приходят из CSV, логов или внешнего API, где все выглядит как строка. Не обязательно сразу строить идеальную модель. Практичный путь — создать staging-таблицу для сырой загрузки, проверить качество данных, а затем переложить их в typed-таблицу через INSERT SELECT

SELECT
    toDate(parseDateTimeBestEffort(event_time)) AS event_date,
    parseDateTimeBestEffort(event_time) AS event_time_typed,
    toUInt64(user_id) AS user_id_typed,
    event_type,
    CAST(amount AS Decimal(12, 2)) AS amount_typed
FROM values(
    'event_time String, user_id String, event_type String, amount String',
    ('2026-07-20 12:34:56', '42', 'purchase', '19.95')
);

Проверенный результат: дата 2026-07-20, время 2026-07-20 12:34:56, пользователь 42 и сумма 19.95. На реальных данных сначала выявите пустые даты, нечисловые id и неожиданные суммы, а затем переносите строки в типизированную таблицу

Что еще влияет на выбор типов

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

Подписаться
Уведомить о
guest
0 комментариев
Старые
Новые Популярные

Настройки cookie

0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x