Вступить в клуб →
средняявопросХранилища и распределённая обработка

Фильтр не по префиксу ключа сортировки сканирует всю таблицу

Таблица в ClickHouse:

CREATE TABLE fct_events (
    event_date Date,
    client_id  UInt64,
    event_type LowCardinality(String),
    amount     Decimal(18, 2)
) ENGINE = MergeTree
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_date, client_id);

Отчёты по периодам работают быстро. Но запрос службы поддержки «вся история одного клиента» без ограничения по дате читает почти всю таблицу и идёт минутами:

SELECT * FROM fct_events WHERE client_id = 981234;

Почему так и что здесь уместно сделать?

  • Разреженный первичный индекс работает по префиксу ключа сортировки: без условия на event_date гранулы не отсекаются. Помогут ограничение периода, skipping-индекс или проекция с порядком (client_id, event_date).
  • Нужно построить обычный вторичный индекс по client_id: в MergeTree он устроен так же, как B-tree в PostgreSQL, и даёт точечный доступ к строкам по значению.
  • Проблема во фрагментации: запрос вынужден обходить сотни активных кусков, и после OPTIMIZE TABLE ... FINAL они сольются, а поиск по client_id станет быстрым.
  • Нужно добавить client_id в ключ партиционирования: данные каждого клиента лягут в отдельную партицию, и запрос прочитает ровно её.

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела