Лучшие практики работы со словарями
На этой странице приведены практические рекомендации по выбору подходящей структуры словаря, пониманию того, когда словари работают лучше, чем соединение, а когда нет, а также по мониторингу использования словарей.
Введение в словари с подробными примерами см. в основном руководстве по словарям.
Когда использовать словари вместо соединения
Словари лучше всего подходят, когда одна из сторон соединения — это справочная таблица, которая целиком помещается в память. При обычном соединении ClickHouse строит хеш-таблицу по правой стороне, а затем выполняет по ней поиск значений из левой — даже если позже фильтры WHERE отбрасывают большую часть строк. Хотя в последних версиях (24.12+) во многих случаях фильтры применяются до соединения, это не всегда снимает накладные расходы. При использовании словаря dictGet вызывается напрямую, поэтому обращения выполняются только для строк, которые уже прошли фильтрацию.
Однако dictGet подходит не всегда. Если вам нужно вызывать dictGet для значительной доли строк таблицы — например, в условии WHERE вида dictGet('dict', 'elevation', id) > 1800 — лучше использовать обычный столбец со встроенными индексами. ClickHouse может использовать PREWHERE, чтобы пропускать гранулы для обычного столбца, тогда как dictGet вычисляется построчно и не поддерживает индексы.
Как правило:
- Используйте словари вместо соединения с небольшими таблицами измерений, когда ключ поиска уже доступен.
- Используйте обычные столбцы и индексы, когда нужно фильтровать по найденному значению для большого числа строк.
Выбор структуры
Секция LAYOUT задаёт внутреннюю структуру данных словаря. Все доступные структуры описаны в справочнике по структурам словарей.
При выборе структуры используйте следующие рекомендации:
flat— самая быстрая структура (простой поиск по смещению в массиве), но ключи должны иметь типUInt64и по умолчанию ограничены 500 000 (max_array_size). Лучше всего подходит для монотонно возрастающих целочисленных ключей в таблицах малого и среднего размера. Разреженное распределение ключей (например, значения 1 и 500 000) приводит к лишнему расходу памяти, поскольку размер массива определяется по наибольшему ключу. Если вы упираетесь в лимит 500k, это сигнал перейти наhashed_array.hashed_array— рекомендуемый вариант по умолчанию для большинства сценариев использования. Хранит атрибуты в массивах, а хэш-таблица сопоставляет ключи с индексами массива. Почти так же быстр, какhashed, но использует память эффективнее, особенно при большом количестве атрибутов.hashed— хранит весь словарь в хэш-таблице. Может быть быстрее, чемhashed_array, если атрибутов очень мало, но потребляет больше памяти по мере роста их числа.complex_key_hashed/complex_key_hashed_array— используйте их, если ключи нельзя привести кUInt64(например, ключи типаString). Для них действуют те же компромиссы по производительности, что и для соответствующих структур без complex key.sparse_hashed— снижает потребление памяти по сравнению сhashedценой дополнительной нагрузки на CPU. Редко бывает лучшим выбором — эффективен только при наличии одного атрибута. В большинстве случаев лучше подходитhashed_array.cache/ssd_cache— кэшируют только часто запрашиваемые ключи. Полезны, когда весь набор данных не помещается в памяти, но при промахах кэша обращения могут идти к источнику. Не рекомендуются для рабочих нагрузок, чувствительных к задержкам.direct— обращается к источнику при каждом поиске без хранения данных в памяти. Используйте, когда данные изменяются слишком часто для кэширования или когда словарь слишком велик, чтобы целиком хранить его в памяти.
Мониторинг использования словарей
Отслеживайте потребление памяти и состояние с помощью таблицы system.dictionaries:
Ключевые столбцы:
bytes_allocated— объем памяти, занимаемой словарем. Словари хранят данные в несжатом виде, поэтому этот объем может значительно превышать размер таблицы в сжатом виде.hit_rateиfound_rate— полезны для оценки эффективности словаря с компоновкойcache.last_exception— проверьте это поле, если словарь не удается загрузить или обновить.