166 lines
5.4 KiB
SQL
166 lines
5.4 KiB
SQL
-- Индексы и сжатие - Индексы --
|
||
|
||
-- #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 будет больше одного. Нет гарантии, что данные на выходе будут корректные.
|
||
*/ |