TGViewer
Дата Инженер Лаб | Артём Подвальный Дата Инженер Лаб | Артём Подвальный @dataengineerlab · 1.87K subscribers
Post #54 2.18K
❓ Сегодня продолжим про ClickHouse — на этот раз про гранулы, ORDER BY и индексы

В прошлом посте мы посмотрели на ClickHouse в целом: колоночное хранение, Block’и, Part’ы и MergeTree.
Теперь разберёмся, как именно ClickHouse читает данные так быстро — за счёт организации данных внутри Part и индексов.

Что такое гранула в ClickHouse?
🔘Внутри каждой Part данные делятся на гранулы (granules) — минимальные куски чтения.По умолчанию index_granularity = 8192 строк.
То есть Part логически разбивается на блоки по ~8192 строк.
🔘ClickHouse всегда читает данные гранулами, а не по одной строке.
Если запрос зацепил хотя бы одну строку в грануле — на диск идёт чтение всего блока (но только нужных колонок).

⚙️ORDER BY и Primary Key

ORDER BY (...) в MergeTree — это кластеризационный ключ. Он Определяет физический порядок строк внутри Part.
PRIMARY KEY обычно тот же самый ORDER BY и нужен для ускорения диапазонных запросов, а не для уникальности.

📎Primary index

Primary index
в ClickHouse — это разреженный индекс по гранулам: Для каждой гранулы хранится значение ключа ORDER BY первой строки. По WHERE ClickHouse выбирает только те гранулы, которые могут подойти, и читает с диска только их. Индекс не ищет строку, он помогает пропустить лишние куски данных.

📝Skip-индексы.Помимо primary index, существуют skip-индексы (data skipping indexes) — дополнительные структуры, которые помогают ещё агрессивнее пропускать гранулы.

minmax - Сохраняет минимум и максимум по колонке внутри гранулы.
Если min(price) > 1000, а запрос ищет price < 500, эту гранулу можно не читать вообще.

set - Хранит множество значений (до лимита).
Если в set-индексе по грануле нет искомого значения — гранула отбрасывается.

bloom_filter / ngrambf_v1 / tokenbf_v1 - Индексы для IN (...), текстового поиска, LIKE и т.п.
Они позволяют не лезть в гранулу, если точно понятно, что внутри нет нужного токена / хеша.
Важно: skip-индексы работают поверх гранул, а не по строкам.
И их имеет смысл добавлять только там, где колонка часто участвует в фильтрах WHERE, и распределение значений позволяет реально отбрасывать куски данных.

Где это использовать?

➡️PARTITION BY - Используется для грубого разбиения данных (по датам, бизнес-ключам).
Партиции позволяют сразу выбросить огромные куски таблицы (например, старые месяцы).
➡️ ORDER BY - Определяет, как строки лежат внутри партиции.
Первый столбец в ORDER BY обычно выбирают под самый частый и селективный фильтр (например, user_id, category_id, date — зависит от витрины).
➡️ Primary index - Работает по тому же выражению, что ORDER BY, и решает, какие гранулы читать.
Чем более «упорядочены» данные относительно реальных запросов, тем меньше гранул будет затронуто.
➡️ Skip-индексы. Используются точечно — для тяжёлых фильтров (по тексту, IN (...), длинным спискам и т.д.), когда простого порядка ORDER BY недостаточно.
  • 🔥 12
  • 👍 6
  • 👀 5
  • ❤ 3
More from @dataengineerlab
  1. Sep 20, 2026Как вкатиться в Data Engineering с нуля? 🗺 Самая частая ошибка новичков- пытаться сразу в…
  2. Sep 17, 2026CDC и Debezium: как передавать изменения, а не выгружать всю таблицу заново? Допустим, зак…
  3. Sep 13, 2026Тебе тоже кажется, что забываешь быстрее, чем учишь? Недавно менти поделился проблемой: по…
  4. Sep 10, 2026Мини гайд по ИИ-агентам Агент снова забыл условия задачи, полез менять лишнее или написал…
  5. Sep 3, 2026До конца года 4 месяца. Что можно успеть? 📖 Лето закончили с сильными результатами: 13 ме…
  6. Aug 30, 2026Что такое векторные базы данных? Представим, что пользователь пишет📝: «Не проходит оплата…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →