Learning Platform
Глоссарий Troubleshooting
Урок 06.07 · 10 мин
Начальный
Skip IndexText IndexSelectivitySAMPLE BYDictionarydictGetSummary

Итоги модуля: skip-индексы и словари

Модуль покрывает два механизма ускорения запросов: skip-индексы (вторичные индексы, пропускающие блоки данных) и словари (pre-loaded lookup-структуры, заменяющие JOIN). Оба дополняют primary key — skip-индексы фильтруют по столбцам вне ORDER BY, словари обогащают факты dimension-атрибутами без rebuild hash table.


Quick reference: skip-индексы

Синтаксис создания

-- При CREATE TABLE
CREATE TABLE logs (
    timestamp DateTime,
    user_id UInt64,
    message String,
    INDEX idx_user user_id TYPE set(100) GRANULARITY 4,
    INDEX idx_msg message TYPE tokenbf_v1(30720, 2, 0) GRANULARITY 1
) ENGINE = MergeTree()
ORDER BY timestamp;

-- ALTER TABLE (добавление к существующей таблице)
ALTER TABLE logs ADD INDEX idx_status status TYPE minmax GRANULARITY 2;
ALTER TABLE logs MATERIALIZE INDEX idx_status;

5 типов skip-индексов

ТипЧто хранитДля каких запросовGRANULARITY
minmaxMin/max значения в блокеRange: WHERE x > 100, BETWEEN2-4
set(N)N уникальных значенийEquality: WHERE status = 'ok', IN (...)2-4
bloom_filterВероятностный фильтрEquality, IN, has() для массивов1-2
ngrambf_v1N-gram Bloom filter (legacy)LIKE '%text%', hasToken()1
tokenbf_v1Token Bloom filter (legacy)hasToken(), equality по словам1
WARNING

ngrambf_v1 и tokenbf_v1 — legacy. Для full-text поиска используйте text index (inverted index), GA с ClickHouse 26.2. Text index в 7-10x быстрее и не имеет ложных срабатываний Bloom filter.

Text index (inverted index)

-- Современная замена ngrambf_v1/tokenbf_v1
ALTER TABLE logs ADD INDEX idx_search message TYPE text GRANULARITY 1;
ALTER TABLE logs MATERIALIZE INDEX idx_search;

-- Использование: hasToken(), multiSearchAny(), LIKE
SELECT * FROM logs WHERE hasToken(message, 'error');

Quick reference: SAMPLE BY

-- Создание таблицы с SAMPLE BY
CREATE TABLE events (
    user_id UInt64,
    event_type String,
    timestamp DateTime
) ENGINE = MergeTree()
ORDER BY (intHash32(user_id), timestamp)
SAMPLE BY intHash32(user_id);

-- Детерминированная 10% выборка
SELECT count(), uniq(user_id)
FROM events
SAMPLE 0.1;

-- _sample_factor: коэффициент экстраполяции
SELECT count() * _sample_factor AS estimated_total
FROM events
SAMPLE 0.01;

Quick reference: словари

CREATE DICTIONARY

CREATE DICTIONARY country_dict (
    code String,
    country_name String,
    continent String
)
PRIMARY KEY code
SOURCE(CLICKHOUSE(TABLE 'countries' DB 'default'))
LAYOUT(HASHED())
LIFETIME(MIN 300 MAX 600);

dictGet()

-- Обогащение: dictGet(dict, attr, key)
SELECT
    event_id,
    dictGet('country_dict', 'country_name', country_code) AS country
FROM events;

-- С default-значением для missing keys
SELECT dictGetOrDefault('country_dict', 'country_name', code, 'Unknown')
FROM events;

-- Direct Join: JOIN через словарь (до 25x быстрее hash join)
SET join_algorithm = 'direct';
SELECT e.*, c.country_name
FROM events e LEFT JOIN country_dict c ON e.country_code = c.code;

Выбор layout-а

СценарийLayoutПочему
UInt64 ключи, до 500K записейflatМассив, fastest O(1)
UInt64 ключи, 100K-10M записейhashedHash table, fast O(1)
Составной ключ (country + city)complex_key_hashedMulti-column hash
IP-геолокация по CIDRip_trieLongest prefix match
Огромный словарь, hot key patterncacheLRU, только hot keys в RAM
Date-range lookup (курсы валют)range_hashedMin/max range match

Ключевые выводы по модулю

  1. Skip-индексы пропускают блоки гранул по агрегированной информации. GRANULARITY skip-индекса — количество гранул на один блок (не строк). GRANULARITY=1 — самый точный.

  2. Selectivity определяет эффективность skip-индекса. Низкая кардинальность (status, country) — хорошо. Высокая кардинальность (user_id, timestamp) — skip-индекс бесполезен (каждый блок содержит нужные значения).

  3. Text index (inverted, GA 26.2) заменяет legacy ngrambf_v1/tokenbf_v1. Точный (нет false positives), в 7-10x быстрее. Используйте для full-text поиска.

  4. SAMPLE BY — детерминированная выборка для approximate queries. intHash32() обеспечивает равномерное распределение. _sample_factor — коэффициент экстраполяции.

  5. Словари загружают справочные данные в RAM. LAYOUT определяет структуру (flat/hashed/cache/ip_trie/…). LIFETIME рандомизирует обновление между репликами.

  6. dictGet() заменяет JOIN для dimension enrichment. Pre-loaded lookup без rebuild hash table на каждый запрос. Direct Join (join_algorithm='direct') — до 25x быстрее hash join при сохранении SQL JOIN синтаксиса.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Какой тип skip-индекса заменяет устаревшие ngrambf_v1 и tokenbf_v1 для full-text поиска в ClickHouse 26.2+?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7