From 1de11c1d5e7a45835fa6c8ae39f36c1f734a2dd1 Mon Sep 17 00:00:00 2001 From: Bonifatsiy Date: Mon, 4 May 2026 08:09:54 +0400 Subject: [PATCH] =?UTF-8?q?=D0=98=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=D1=8B=20?= =?UTF-8?q?=D0=B8=20=D1=81=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20-=20=D0=98?= =?UTF-8?q?=D0=BD=D0=B4=D0=B5=D0=BA=D1=81=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Homework/Индексы и сжатие - Индексы.sql | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql diff --git a/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql new file mode 100644 index 0000000..9332b35 --- /dev/null +++ b/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql @@ -0,0 +1,166 @@ +-- Индексы и сжатие - Индексы -- + +-- #1 +/* +3. Посмотри, сколько блоков было пропущено (в `system.query_log`, `rows_read`, `rows`). +Не посмотрю, так как нет доступа system.query_log, rows_read, rows (ACCESS_DENIED) +4. Что будет, если `ORDER BY log_id`, а не `ts`? +ORDER BY log_id → данные физически отсортированы по log_id. Значения ts расположены хаотично относительно физической сортировки. +Индекс minmax по ts будет почти бесполезен. Minmax индекс будет иметь широкие диапазоны +*/ + +DROP TABLE IF EXISTS dsolovianov.logs ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.logs +ON CLUSTER clickhouse_cluster +( + log_id UInt64, + ts DateTime +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/logs', + '{replica}' +) +ORDER BY ts +PARTITION BY toYYYYMM(ts) +PRIMARY KEY (ts); + +INSERT INTO dsolovianov.logs (log_id, ts) VALUES +(1, '2024-06-01 10:00:00'), +(2, '2024-06-01 11:00:00'), +(3, '2024-06-02 12:00:00'), +(4, '2024-06-03 13:00:00'), +(5, '2024-06-04 14:00:00'); + +-- 1. Добавляем minmax индекс: +ALTER TABLE dsolovianov.logs ADD INDEX idx_ts ts TYPE minmax GRANULARITY 2; + +-- 2. Сделай запрос: `SELECT * FROM logs WHERE ts BETWEEN '2024-06-02' AND '2024-06-03'` +SELECT * +FROM dsolovianov.logs +WHERE ts + BETWEEN '2024-06-02' AND '2024-06-03'; + +-- Раз нет доступа, но можно предположить, что вот такой запрос сработает: +SELECT query, read_rows, result_rows +FROM system.query_log +WHERE query LIKE '%logs%' +ORDER BY event_time DESC +LIMIT 1; + + +-- #2 +/* +1. Создай таблицу с `ORDER BY id`, добавь индекс: + + ```sql + ALTER TABLE clicks ADD INDEX idx_country country TYPE set(1000) GRANULARITY 2; + ``` + + +3. Посмотри `EXPLAIN` — индекс используется? +Данные отсортированы по id, а не по country. Значения country распределены хаотически относительно физического порядка. +4. Как будет вести себя индекс, если `country` имеет 10M уникальных значений? +Будет создано 10M партиций, что убьёт производительность. +**/ +DROP TABLE IF EXISTS dsolovianov.clicks ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.clicks +ON CLUSTER clickhouse_cluster +( + id UInt64, + country String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/clicks', + '{replica}' +) +ORDER BY id +PARTITION BY country +PRIMARY KEY (id); + +INSERT INTO dsolovianov.clicks (id, country) VALUES +(1, 'RU'), +(2, 'US'), +(3, 'RU'), +(4, 'DE'), +(5, 'RU'); + +ALTER TABLE dsolovianov.clicks ON CLUSTER clickhouse_cluster +ADD INDEX idx_country country TYPE set(1000) GRANULARITY 2; + +-- 2. Выполни запрос `SELECT * FROM clicks WHERE country = 'RU'`. +EXPLAIN indexes = 1 +SELECT * FROM dsolovianov.clicks WHERE country = 'RU'; + +EXPLAIN +SELECT * FROM dsolovianov.clicks WHERE country = 'RU'; + +/* +Expression ((Project names + Projection)) + Expression ((WHERE + Change column names to column identifiers)) + ReadFromMergeTree (dsolovianov.clicks) + Indexes: + MinMax + Keys: + country + Condition: (country in ['RU', 'RU']) + Parts: 1/3 + Granules: 1/3 + Partition + Keys: + country + Condition: (country in ['RU', 'RU']) + Parts: 1/1 + Granules: 1/1 + PrimaryKey + Condition: true + Parts: 1/1 + Granules: 1/1 + Skip + Name: idx_country + Description: set GRANULARITY 2 + Parts: 1/1 + Granules: 1/1 + Ranges: 1 + */ + +-- #3 + +DROP TABLE IF EXISTS dsolovianov.users ON CLUSTER clickhouse_cluster SYNC; + +CREATE TABLE dsolovianov.users +ON CLUSTER clickhouse_cluster +( + id UInt64, + email String +) +ENGINE = ReplicatedMergeTree( + '/clickhouse/tables/{shard}/dsolovianov/users', + '{replica}' +) +ORDER BY id +PRIMARY KEY (id); + +INSERT INTO dsolovianov.users (id, email) VALUES +(1, 'alice@mail.com'), +(2, 'bob@mail.com'), +(3, 'charlie@mail.com'), +(4, 'dave@mail.com'), +(5, 'eve@example.com'); + +ALTER TABLE dsolovianov.users ADD INDEX idx_email email TYPE bloom_filter(0.01) GRANULARITY 2; + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email = 'alice@mail.com'; +-- Bloom filter может пропустить некоторые гранулы, но не все, ибо данные не отсортированы по email и индексные блоки покрывают случайные email'ы + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email LIKE '%mail%'; + +EXPLAIN indexes = 1 +SELECT * FROM users WHERE email LIKE 'alice%'; +/* +Bloom filter не поддерживает частичные совпадения (LIKE '..%', LIKE '%..', LIKE '%..%'). Из-за этого ClickHouse не может пропустить гранулы. +Клику становится сложно вычислить хэш для проверки, если подходящих значений по LIKE будет больше одного. Нет гарантии, что данные на выходе будут корректные. +*/ \ No newline at end of file