Кэш данных
Data Cache ускоряет последующие запросы к тем же данным, кэшируя недавно использованные файлы данных из удалённых систем хранения (HDFS или объектных хранилищ) на локальных дисках. При частом обращении к одним и тем же данным Data Cache позволяет избежать накладных расходов на повторное чтение из удалённого хранилища, повышая производительность и стабильность аналитических запросов к горячим данным.
Сценарии применения
Кэширование данных работает только для запросов к таблицам Hive, Iceberg, Hudi и Paimon. Оно не влияет на запросы к внутренним таблицам или внешним таблицам, не основанным на файлах (например, JDBC, Elasticsearch).
Возможность повышения эффективности запросов с помощью кэширования данных зависит от нескольких факторов. Ниже перечислены условия, при которых целесообразно использовать кэширование данных:
-
Высокоскоростной локальный диск
Каталог кэша данных рекомендуется размещать на высокоскоростных локальных дисках, например SSD или NVME. Механические жёсткие диски для этого не рекомендуются. Для заметного прироста производительности пропускная способность IO и IOPS локального диска должны значительно превышать пропускную способность сети, а также пропускную способность IO и IOPS исходной системы хранения.
-
Достаточный объём кэша
Для вытеснения данных из кэша используется стратегия LRU. Если в запрашиваемых данных нет чёткого разделения на горячие и холодные, содержимое кэша может часто обновляться и заменяться, что способно снизить производительность запросов. Рекомендуется включать кэширование данных, когда характер запросов предполагает чёткое разделение на горячие и холодные данные (например, большинство запросов обращается только к сегодняшним данным и редко затрагивает исторические), а объёма кэша достаточно для хранения горячих данных.
-
Нестабильная задержка IO удалённого хранилища
Такая ситуация обычно возникает при использовании HDFS. В большинстве компаний разные подразделения совместно используют одну и ту же систему HDFS, из-за чего задержка IO в периоды пиковой нагрузки может быть очень нестабильной. Если в таких условиях требуется обеспечить стабильную задержку IO, рекомендуется включить кэширование данных. При этом необходимо учитывать и первые два условия.
Включение Data Cache
Начиная с Doris 4.2, Data Cache включён по умолчанию: и параметр BE enable_file_cache, и переменная сеанса enable_file_cache по умолчанию имеют значение true. Для использования кэша настройте его каталог в be.conf; с помощью параметра FE можно включать или отключать кэширование для отдельного сеанса или глобально.
Настройка BE
Сначала укажите параметры пути кэша в be.conf и перезапустите узел BE, чтобы настройки вступили в силу.
| Параметр | Обязательный | Описание |
|---|---|---|
enable_file_cache | Нет | Включает Data Cache. Начиная с Doris 4.2, включён по умолчанию. |
file_cache_path | Да | Настройки каталога кэша в формате JSON. |
clear_file_cache | Нет | По умолчанию false. Если установлено true, каталог кэша очищается при перезапуске узла BE. |
Пример настройки file_cache_path:
file_cache_path=[{"path": "/path/to/file_cache1", "total_size":53687091200},{"path": "/path/to/file_cache2", "total_size":53687091200},{"path": "/path/to/file_cache3", "total_size":53687091200}]
path — путь для хранения кэша. Можно указать один или несколько путей. Рекомендуется настраивать только один путь на каждом диске.
total_size — максимальный объём кэша в байтах. При превышении этого объёма кэшированные данные вытесняются по стратегии LRU.
Настройка FE
Включение Data Cache для отдельного сеанса:
SET enable_file_cache = true;
Глобальное включение Data Cache:
SET GLOBAL enable_file_cache = true;
При сканировании внешних файлов чтение через кэш выполняется только в том случае, если включены параметр BE enable_file_cache, переменная сеанса enable_file_cache и контроль допуска в кэш. На внутренние таблицы переменная сеанса не влияет.
- На BE в режиме совмещения хранения и вычислений, где не задан
file_cache_path, кэш создаётся в${DORIS_HOME}/file_cacheи при отсутствииtotal_sizeможет расти до заполнения диска на 85%–88%. Задайтеfile_cache_pathсtotal_size, чтобы ограничить его объём, или установитеenable_file_cache = falseвbe.conf, чтобы сохранить прежнее поведение. - Настройки BE не сохраняются в постоянном хранилище, поэтому после обновления BE использует значение по умолчанию, встроенное в его исполняемый файл, если ключ не задан в
be.conf. Переменные сеанса сохраняются в образе FE, поэтому кластер, обновлённый с более ранней версии, сохраняет прежнее значение; чтобы кэшировать внешние таблицы после обновления, выполнитеSET GLOBAL enable_file_cache = true.
Наблюдаемость кэша
Просмотр доли попаданий в кэш
Выполните set enable_profile=true, чтобы включить соответствующую переменную сеанса. После этого профиль задания можно просмотреть на вкладке Queries веб-интерфейса FE. Метрики кэша данных приведены ниже:
- FileCache: 0ns
- BytesScannedFromCache: 2.02 GB
- BytesScannedFromRemote: 0.00
- BytesWriteIntoCache: 0.00
- LocalIOUseTimer: 2s723ms
- NumLocalIOTotal: 444
- NumRemoteIOTotal: 0
- NumSkipCacheIOTotal: 0
- RemoteIOUseTimer: 0ns
- WriteCacheIOUseTimer: 0ns
-
BytesScannedFromCache: объём данных, прочитанных из локального кэша. -
BytesScannedFromRemote: объём данных, прочитанных из удалённого хранилища. -
BytesWriteIntoCache: объём данных, записанных в кэш. -
LocalIOUseTimer: время IO локального кэша. -
RemoteIOUseTimer: время IO при чтении из удалённого хранилища. -
NumLocalIOTotal: количество операций IO с локальным кэшем. -
NumRemoteIOTotal: количество удалённых операций IO. -
WriteCacheIOUseTimer: время IO при записи в кэш.
Если BytesScannedFromRemote равно 0, все данные были прочитаны из кэша.
Метрики мониторинга
Статистику кэша для каждого узла Backend можно просмотреть в системной таблице file_cache_statistics.
Ограничения использования кэша запросом
Doris предоставляет два независимых механизма управления Data Cache на уровне запроса:
| Механизм | Основной параметр | Поведение после достижения ограничения |
|---|---|---|
| Ограничение по доле занятого кэша | file_cache_query_limit_percent | Заполнение кэша при промахах остаётся разрешённым, а BE освобождает место с помощью записей LRU на уровне запроса и других очередей кэша |
| Прекращение записи в кэш при удалённом сканировании по порогу в байтах | file_cache_query_limit_bytes | Если следующий блок кэша приведёт к превышению порога допущенного объёма данных, при последующих промахах данные будут читаться из удалённого хранилища без заполнения локального кэша |
Ограничение по доле занятого кэша
Эта функция поддерживается начиная с версии 4.0.3.
Ограничение по доле занятого кэша задаёт максимальную долю каждого экземпляра File Cache, которую может использовать один запрос. Когда несколько пользователей или сложных запросов совместно используют ресурсы кэша, это снижает риск того, что один большой запрос удержит слишком большой объём кэша и вытеснит другие горячие данные.
Эта функция требует настройки BE и FE, а также переменных сеанса.
1. Настройка BE
enable_file_cache_query_limit:- Тип: Boolean
- По умолчанию:
false - Описание: основной переключатель функции ограничения использования файлового кэша запросом на стороне BE. BE обрабатывает параметры ограничения, переданные из FE, только при включении этого переключателя.
2. Настройка FE
file_cache_query_limit_max_percent:- Тип: Integer
- По умолчанию:
100 - Описание: максимальное допустимое ограничение для запроса, используемое при проверке верхней границы переменной сеанса.
3. Переменные сеанса
file_cache_query_limit_percent:- Тип: Integer (1-100)
- По умолчанию:
-1 - Описание: максимальная доля кэша в процентах, которую может использовать запрос. Это значение ограничено параметром
file_cache_query_limit_max_percent. Рассчитанная квота кэша должна составлять не менее 256 MB; в противном случае BE записывает предупреждение в журнал.
Пример использования
-- Set the session variable to limit a query to at most 50% of the cache
SET file_cache_query_limit_percent = 50;
-- Execute the query
SELECT * FROM large_table;
Примечания:
- Значение должно находиться в диапазоне
[1, file_cache_query_limit_max_percent]. - Перед использованием этого механизма включите на BE оба параметра:
enable_file_cacheиenable_file_cache_query_limit, а также убедитесь, что в сеансе запроса переменнаяenable_file_cacheимеет значениеtrue. - После достижения процентной квоты запись в Data Cache при промахах остаётся разрешённой. Этот механизм не переводит запрос в режим прекращения дальнейшей записи.
Прекращение записи в кэш при удалённом сканировании по порогу в байтах
Эта функция поддерживается только в Doris 4.1.x. В Doris 4.0.x она не поддерживается.
В режиме разделения вычислений и хранения переменная сеанса file_cache_query_limit_bytes ограничивает суммарный объём данных в байтах, допущенных к заполнению Data Cache при промахах кэша файлов данных Hive, Iceberg, Hudi или Paimon для одного запроса SELECT на каждом BE. Для её работы на BE требуется enable_file_cache=true, но она не зависит от enable_file_cache_query_limit или file_cache_query_limit_max_percent.
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
file_cache_query_limit_bytes | BigInt | -1 | Порог заполнения кэша при удалённом сканировании для одного запроса на каждом BE, в байтах. Значение ниже 0 отключает этот механизм; 0 отключает заполнение кэша с самого начала запроса; при положительном значении допущенный объём данных накапливается по блокам кэша |
Параллельные сканеры одного запроса используют общий порог на одном BE. Этот порог не является суммарным ограничением для всего запроса или кластера. Если следующий блок кэша приведёт к превышению порога допущенного объёма данных, запрос на этом BE переходит в режим remote-only-on-miss: диапазон запроса, полностью покрытый локальным кэшем, по-прежнему может быть прочитан локально; диапазон, покрытый не полностью, читается непосредственно из удалённого хранилища без заполнения Data Cache. Результат запроса не меняется.
В следующем примере на каждом BE устанавливается порог заполнения кэша при удалённом сканировании в 1 GiB:
SET enable_profile = true;
SET profile_level = 2;
SET file_cache_query_limit_bytes = 1073741824;
SELECT COUNT(*) FROM hive_catalog.sales.orders;
Чтобы запретить запись в Data Cache при разовом сканировании с самого начала, установите порог в 0, а после запроса восстановите значение по умолчанию:
SET file_cache_query_limit_bytes = 0;
SELECT COUNT(*) FROM hive_catalog.sales.orders;
SET file_cache_query_limit_bytes = -1;
После включения Query Profile проверьте RemoteOnlyOnMissTriggered и RemoteOnlyOnMissThresholdBytes в группе метрик FileCache сканера. Если RemoteOnlyOnMissTriggered=1, сканер зафиксировал переход запроса в режим remote-only-on-miss. Используйте BytesWriteIntoCache и NumSkipCacheIOTotal для проверки фактических записей и операций I/O, выполненных в обход кэша. Поскольку NumSkipCacheIOTotal также может учитывать операции I/O, для которых кэш был пропущен из-за других политик кэширования, одной этой метрики недостаточно, чтобы подтвердить срабатывание порога.
- Этот механизм применяется только к заполнению Data Cache при промахах запросов SELECT в режиме разделения вычислений и хранения. Он не ограничивает объём данных, прочитанных из удалённого хранилища, и не влияет на явный прогрев кэша. Режим remote-only-on-miss может увеличить количество удалённых операций I/O и задержку запросов.
- Допуск оценивается по блокам кэша. Если оставшегося лимита не хватает для следующего блока, весь блок пропускается.
RemoteOnlyOnMissTriggeredменяется на1только тогда, когда запись блока привела бы к превышению порога. - Параметр BE
enable_file_cache_query_limit_segment_metaопределяет, учитываются ли при расчёте того же порога записи footer и метаданных Segment внутренних таблиц Doris. На заполнение кэша для файлов данных Hive, Iceberg, Hudi и Paimon всегда распространяетсяfile_cache_query_limit_bytes. Полную область действия параметров и поведение для внутренних таблиц см. в руководстве по настройке и использованию File Cache.
Прогрев кэша
Data Cache предоставляет функцию «прогрева» кэша, которая позволяет заранее загружать внешние данные в локальный кэш узлов BE. Это повышает долю попаданий в кэш и производительность первых запросов, выполняемых после прогрева.
Эта функция поддерживается начиная с версии 4.0.2.
Синтаксис
WARM UP SELECT <select_expr_list>
FROM <table_reference>
[WHERE <boolean_expression>]
Ограничения использования:
-
Поддерживаются:
- Запросы к одной таблице (допускается только один table_reference)
- Простой SELECT для указанных столбцов
- Фильтрация WHERE (поддерживаются обычные предикаты)
-
Не поддерживаются:
- JOIN, UNION, подзапросы, CTE
- GROUP BY, HAVING, ORDER BY
- LIMIT
- INTO OUTFILE
- Планы запросов с несколькими таблицами или сложные планы запросов
- Другие сложные синтаксические конструкции
Примеры
- Прогрев всей таблицы
WARM UP SELECT * FROM hive_db.tpch100_parquet.lineitem;
- Прогрев отдельных столбцов по партиции
WARM UP SELECT l_orderkey, l_shipmode
FROM hive_db.tpch100_parquet.lineitem
WHERE dt = '2025-01-01';
- Прогрев отдельных столбцов по условиям фильтрации
WARM UP SELECT l_shipmode, l_linestatus
FROM hive_db.tpch100_parquet.lineitem
WHERE l_orderkey = 123456;
Результаты выполнения
После выполнения WARM UP SELECT FE отправляет задачи каждому BE. BE сканирует удалённые данные и записывает их в Data Cache.
Система сразу возвращает статистику сканирования и записи в кэш для каждого BE (примечание: статистика в целом точна, но возможна некоторая погрешность). Например:
+---------------+-----------+-------------+---------------------------+----------------------------+---------------------+
| BackendId | ScanRows | ScanBytes | ScanBytesFromLocalStorage | ScanBytesFromRemoteStorage | BytesWriteIntoCache |
+---------------+-----------+-------------+---------------------------+----------------------------+---------------------+
| 1755134092928 | 294744184 | 11821864798 | 538154009 | 11283717130 | 11899799492 |
| 1755134092929 | 305293718 | 12244439301 | 560970435 | 11683475207 | 12332861380 |
| TOTAL | 600037902 | 24066304099 | 1099124444 | 22967192337 | 24232660872 |
+---------------+-----------+-------------+---------------------------+----------------------------+---------------------+
Описание полей:
ScanRows: количество просканированных и прочитанных строк.ScanBytes: объём просканированных и прочитанных данных.ScanBytesFromLocalStorage: объём данных, просканированных и прочитанных из локального кэша.ScanBytesFromRemoteStorage: объём данных, просканированных и прочитанных из удалённого хранилища.BytesWriteIntoCache: объём данных, записанных в Data Cache во время этого прогрева.
Контроль допуска в кэш
Это экспериментальная функция, которая поддерживается начиная с версии 4.1.0.
Функция контроля допуска в кэш позволяет определять, могут ли данные, прочитанные запросом, попадать в File Cache (Data Cache), на основе таких характеристик, как пользователь, Catalog, база данных и таблица. При массовом чтении холодных данных (например, в масштабных заданиях ETL или ресурсоёмких нерегламентированных запросах) разрешение кэшировать все прочитанные данные может привести к частому вытеснению уже находящихся в кэше горячих данных («загрязнению кэша»). Это снижает долю попаданий в кэш и общую производительность запросов. Когда функция включена, данные, которым отказано в допуске, читаются непосредственно из удалённого базового хранилища (например, HDFS, S3), что защищает основные горячие данные от вытеснения.
Функция контроля допуска в кэш по умолчанию отключена. Для её включения необходимо настроить соответствующие параметры в FE.
Настройка FE
Включите эту функцию и укажите путь к каталогу файлов правил в fe.conf, затем перезапустите узел FE, чтобы настройки вступили в силу. Изменения самих файлов правил могут загружаться динамически.
| Параметр | Обязательный | Описание |
|---|---|---|
enable_file_cache_admission_control | Да | Включает контроль допуска в кэш. По умолчанию false. |
file_cache_admission_control_json_dir | Да | Путь к каталогу для хранения файлов JSON с правилами допуска. Все файлы .json в этом каталоге загружаются автоматически, а любые добавления, удаления или изменения правил вступают в силу динамически. |
Формат настройки правил допуска
Настройки правил размещаются в файлах .json в каталоге file_cache_admission_control_json_dir. Содержимое файла должно представлять собой массив JSON.
Описание полей
| Имя поля | Тип | Описание | Пример |
|---|---|---|---|
id | Long | Идентификатор правила. | 1 |
user_identity | String | Идентификатор пользователя (формат: user@host, например, % соответствует всем IP-адресам). Если поле пустое или отсутствует, правило действует для всех пользователей. | "root@%" |
catalog_name | String | Имя Catalog. Если поле пустое или отсутствует, правило действует для всех Catalog. | "hive_cat" |
database_name | String | Имя базы данных. Если поле пустое или отсутствует, правило действует для всех баз данных. | "db1" |
table_name | String | Имя таблицы. Если поле пустое или отсутствует, правило действует для всех таблиц. | "tbl1" |
partition_pattern | String | (Пока не реализовано) Регулярное выражение для партиций. Пустое значение соответствует всем партициям. | "" |
rule_type | Integer | Тип правила: 0 запрещает кэширование (чёрный список); 1 разрешает кэширование (белый список). | 0 |
enabled | Integer | Включено ли текущее правило: 0 — отключено; 1 — включено. | 1 |
created_time | Long | Время создания (временная метка UNIX, секунды). | 1766557246 |
updated_time | Long | Время обновления (временная метка UNIX, секунды). | 1766557246 |
Пример файла JSON
[
{
"id": 1,
"user_identity": "root@%",
"catalog_name": "hive_cat",
"database_name": "db1",
"table_name": "table1",
"partition_pattern": "",
"rule_type": 0,
"enabled": 1,
"created_time": 1766557246,
"updated_time": 1766557246
},
{
"id": 2,
"user_identity": "",
"catalog_name": "hive_cat",
"database_name": "",
"table_name": "",
"partition_pattern": "",
"rule_type": 1,
"enabled": 1,
"created_time": 1766557246,
"updated_time": 1766557246
}
]
Импорт правил из MySQL
Для пользователей, которым требуется автоматизированная интеграция с другими системами, в репозитории исходного кода Doris предусмотрен вспомогательный скрипт tools/export_mysql_rule_to_json.sh. С его помощью можно экспортировать правила допуска в кэш, заранее сохранённые в таблице базы данных MySQL, в файлы конфигурации JSON указанного выше формата.
Принципы сопоставления правил
Категории областей действия правил
Комбинируя пустые и конкретные значения полей (user_identity, catalog_name, database_name, table_name), можно задать 7 допустимых вариантов области действия правил. Любая конфигурация правила, нарушающая иерархические зависимости (например, указание таблицы напрямую с пропуском базы данных), считается недопустимой.
| user_identity | catalog_name | database_name | table_name | Уровень и область действия |
|---|---|---|---|---|
| Указано | Указано | Указано | Указано | Правило уровня таблицы для указанного пользователя |
| Пусто или отсутствует | Указано | Указано | Указано | Правило уровня таблицы для всех пользователей |
| Указано | Указано | Указано | Пусто или отсутствует | Правило уровня базы данных для указанного пользователя |
| Пусто или отсутствует | Указано | Указано | Пусто или отсутствует | Правило уровня базы данных для всех пользователей |
| Указано | Указано | Пусто или отсутствует | Пусто или отсутствует | Правило уровня Catalog для указанного пользователя |
| Пусто или отсутствует | Указано | Пусто или отсутствует | Пусто или отсутствует | Правило уровня Catalog для всех пользователей |
| Указано | Пусто или отсутствует | Пусто или отсутствует | Пусто или отсутствует | Глобальное правило для указанного пользователя |
Приоритет и порядок сопоставления
Когда запрос обращается к данным таблицы, система оценивает все правила, чтобы принять решение о допуске. При этом действуют следующие принципы:
- Сначала точное совпадение: сопоставление выполняется от более конкретного уровня иерархии к более общему (таблица → база данных → Catalog → глобальный уровень). Как только найдено совпадение на наиболее точном уровне (например, на уровне таблицы), принятие решения немедленно завершается.
- Приоритет чёрного списка (принцип безопасности): на одном и том же уровне правил запрет кэширования всегда имеет приоритет над разрешением. Если одновременно найдены совпадения с чёрным и белым списками, первым применяется чёрный список, обеспечивая приоритет решений о запрете доступа на этом уровне.
Полная последовательность принятия решения:
1. Table-level rule matching
a) Hit Blacklist (rule_type=0) -> Deny
b) Hit Whitelist (rule_type=1) -> Allow
2. Database-level rule matching
...
3. Catalog-level rule matching
...
4. Global rule matching (only user_identity matched)
...
5. Default fallback decision: If no rules at any level above match, caching is [Denied] by default (equivalent to a global blacklist).
Совет: поскольку при отсутствии совпадений система по умолчанию запрещает кэширование, при внедрении этой функции обычно рекомендуется сначала создать общее разрешающее правило (например, белый список для всех пользователей или для важного бизнес-Catalog), а затем настроить адресные чёрные списки на уровне таблиц для крупных таблиц, которые заведомо подвергаются полному сканированию в пакетных заданиях. Это позволяет точнее разделять холодные и горячие данные.
Наблюдаемость решений о кэшировании
После включения функции и успешного применения настроек подробные решения о допуске в кэш на уровне файловых данных отдельной таблицы можно просмотреть с помощью команды EXPLAIN (см. строку file cache request в выводе ниже).
| 0:VHIVE_SCAN_NODE(74) |
| table: test_file_cache_features.tpch1_parquet.lineitem |
| inputSplitNum=10, totalFileSize=205792918, scanRanges=10 |
| partition=1/1 |
| cardinality=1469949, numNodes=1 |
| pushdown agg=NONE |
| file cache request ADMITTED: user_identity:root@%, reason:user table-level whitelist rule, cost:0.058 ms |
| limit: 1 |
Основные поля и описание решений:
- ADMITTED / DENIED: показывает, разрешено ли запросу помещать данные в кэш (ADMITTED) или в допуске отказано (DENIED).
- user_identity: идентификатор пользователя, проверенный при выполнении этого запроса.
- reason: конкретная причина решения (совпавшее правило), определившая результат. Распространённые значения:
user table-level whitelist rule(в текущем примере — белый список уровня таблицы для указанного пользователя);common table-level blacklist rule(чёрный список уровня таблицы для всех пользователей). Общий формат:[Scope] [Rule Level] [Rule Type] rule. - cost: время выполнения всего расчёта сопоставления правил допуска (в миллисекундах). Если накладные расходы слишком велики, их можно уменьшить, изменив количество уровней иерархии правил.
Приложение
Принцип работы
При кэшировании данные, к которым выполняется обращение в удалённом хранилище, сохраняются на локальном узле BE. Исходный файл данных разделяется на блоки в соответствии с размером запрашиваемых операций IO. Блоки сохраняются в локальном файле cache_path/hash(filepath).substr(0, 3)/hash(filepath)/offset, а их метаданные — на узле BE. При обращении к тому же удалённому файлу Doris проверяет, есть ли его данные в локальном кэше, и по смещению и размеру блоков определяет, какие данные читать из локальных блоков, а какие получать из удалённого хранилища, кэшируя вновь полученные удалённые данные. При перезапуске узел BE сканирует каталог cache_path, чтобы восстановить метаданные блоков. Когда объём кэша достигает верхнего предела, давно не использовавшиеся блоки удаляются по принципу LRU.