Индексы и сжатие - Индексы
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