Индексы и сжатие - Индексы
This commit is contained in:
@@ -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 будет больше одного. Нет гарантии, что данные на выходе будут корректные.
|
||||
*/
|
||||
Reference in New Issue
Block a user