Files
homework/dsolovianov/clickhouse/Homework/Индексы и сжатие - Индексы.sql
2026-05-04 08:09:54 +04:00

166 lines
5.4 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- Индексы и сжатие - Индексы --
-- #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 будет больше одного. Нет гарантии, что данные на выходе будут корректные.
*/