Руководство по настройке и использованию файлового кэша (режим с разделением вычислений и хранения)
В режиме с разделением вычислений и хранения данные хранятся в удалённом объектном хранилище (например, S3 или HDFS). Doris использует локальные диски узлов BE как слой файлового кэша и эффективно управляет пространством кэша с помощью стратегии LRU (Least Recently Used, вытеснение давно не использовавшихся данных) с несколькими очередями. Пути доступа к индексам и метаданным специально оптимизированы для максимального увеличения доли попаданий в кэш для часто используемых данных.
Для сценариев с несколькими вычислительными группами Doris предоставляет функцию прогрева кэша, которая при запуске новой вычислительной группы заранее загружает в неё данные указанных таблиц или партиций. Это позволяет быстро заполнить локальный кэш и повысить производительность первого запроса. Если включено чтение из кэша других BE, блоки, отсутствующие в локальном кэше, сначала запрашиваются из кэша другого BE (в том числе BE из других вычислительных групп), и только затем — из удалённого хранилища.
Роль файлового кэша
В режиме с разделением вычислений и хранения обращение к удалённому хранилищу обычно приводит к следующим двум категориям проблем:
| Проблема | Описание |
|---|---|
| Высокая задержка доступа | Задержка объектного хранилища значительно выше задержки локального диска, что особенно заметно при большом количестве одновременных обращений |
| Ограничения QPS и пропускной способности | Объектное хранилище обычно имеет ограничения QPS и пропускной способности, которые становятся узким местом при большом количестве одновременных запросов |
| Затраты при оплате по использованию | Оплата объектного хранилища зависит от количества запросов и объёма переданных данных, поэтому частые обращения увеличивают эксплуатационные расходы |
Кэшируя часто используемые данные на локальных дисках, Doris может значительно сократить задержку запросов и количество прямых обращений к объектному хранилищу, тем самым снижая затраты.
Типы кэшируемых файлов
Файловый кэш Doris в основном кэширует следующие два типа файлов:
- Файлы данных Segment: базовая единица хранения данных внутренних таблиц Doris. Кэширование этих файлов ускоряет чтение данных и повышает производительность запросов.
- Файлы инвертированных индексов: используются для ускорения операций фильтрации в запросах. Кэширование этих файлов позволяет быстрее находить данные, удовлетворяющие условиям, и поддерживает выполнение сложных запросов.
Настройка кэша
Doris управляет поведением файлового кэша с помощью следующих параметров в файле конфигурации BE.
Включение файлового кэша
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
enable_file_cache | true | Определяет, включён ли файловый кэш. Включён по умолчанию начиная с версии 4.1.5 (ранее — false). В режиме с разделением вычислений и хранения BE всегда принудительно включает его. |
По умолчанию file_cache_path указывает на каталог хранения в каталоге развёртывания BE. Если не задан параметр total_size, кэш может расти, пока диск не заполнится на 85%–88%; задайте total_size, чтобы ограничить его размер.
Необходимо также включить одноимённую переменную сеанса. Сведения о значениях и значениях по умолчанию при обновлении см. в справочнике Переменные сеанса.
Настройка записи в кэш только индексов
Если пространство локального кэша ограничено, а производительность запросов в большей степени зависит от индексов и метаданных Segment, можно включить политику записи только индексов. Эта политика ограничивает содержимое, которое загрузка данных, Schema Change, Compaction и другие пути записи активно записывают в файловый кэш. Она не влияет на заполнение кэша при выполнении запросов после промаха или на прогрев кэша.
Doris предоставляет одну глобальную политику и две политики для Compaction:
| Параметр | Тип | Значение по умолчанию | Область действия | Описание |
|---|---|---|---|---|
enable_file_cache_write_index_file_only | Boolean | false | Все операции записи rowset в режиме с разделением вычислений и хранения, включая загрузку данных, Schema Change, Cumulative Compaction и Base Compaction | Поддерживается в Doris начиная с версии 4.0.8 в серии 4.0 и с версии 4.1.4 в серии 4.1. При значении true данные Segment не кэшируются активно. После закрытия Segment его footer и диапазоны внутренних индексов синхронно предзагружаются, а отдельные файлы инвертированных индексов по-прежнему записываются в файловый кэш. Этот параметр имеет приоритет над двумя параметрами для Compaction |
enable_file_cache_write_base_compaction_index_only | Boolean | false | Base Compaction | Только если существующая политика Base Compaction уже приняла решение записать результат в файловый кэш, предотвращает активное кэширование файла Segment, сохраняя кэширование отдельных файлов инвертированных индексов. Этот параметр не приводит к кэшированию результатов Base Compaction, которые иначе обошли бы кэш |
enable_file_cache_write_cumu_compaction_index_only | Boolean | false | Cumulative Compaction | Когда результат Cumulative Compaction записывается в файловый кэш, предотвращает активное кэширование файла Segment, сохраняя кэширование отдельных файлов инвертированных индексов |
Путь записи определяет поведение кэша в следующем порядке приоритета:
enable_file_cache=falseимеет наивысший приоритет и отключает все операции записи в файловый кэш, включая предзагрузку footer и внутренних индексов Segment и запись отдельных инвертированных индексов.- Если заданы
enable_file_cache=trueиenable_file_cache_write_index_file_only=true, включается глобальная политика записи только индексов. Два параметра для Compaction больше не влияют на итоговое поведение. Адаптивная запись, политики сохранения результатов Compaction, пороги доли попаданий в кэш и настройкиwrite_file_cacheна уровне запроса не могут привести к активному кэшированию данных Segment; содержимое, связанное с индексами, по-прежнему записывается в соответствии с описанной выше глобальной политикой. - Когда глобальная политика записи только индексов отключена, параметры для Base/Cumulative Compaction лишь дополнительно ограничивают результат соответствующего типа, уже выбранный для кэширования. Они не влияют на другие сценарии записи или на путь чтения запросов.
- Когда все три параметра записи только индексов имеют значение
false, существующее поведение активной записи в кэш, адаптивной записи и сохранения результатов Compaction остаётся прежним.
Два параметра для Compaction различают только отдельные файлы инвертированных индексов и файлы Segment. Они не запускают предзагрузку диапазонов footer и внутренних индексов Segment, используемую глобальной политикой записи только индексов. Чтобы активно сохранять как отдельные инвертированные индексы, так и внутренние индексы и метаданные Segment, используйте enable_file_cache_write_index_file_only.
Включение глобальной политики записи только индексов
Задайте следующие настройки в be.conf на каждом узле BE:
enable_file_cache=true
enable_file_cache_write_index_file_only=true
enable_file_cache_write_base_compaction_index_only=false
enable_file_cache_write_cumu_compaction_index_only=false
Ожидаемое поведение:
| Сценарий | Содержимое, активно записываемое в файловый кэш |
|---|---|
| Загрузка данных, Schema Change, Cumulative Compaction и Base Compaction | Данные Segment активно не записываются; диапазоны footer и внутренних индексов Segment синхронно предзагружаются; отдельные файлы инвертированных индексов записываются |
| Чтение страниц данных при выполнении запросов | Поведение не меняется. После промаха кэша данные Segment по-прежнему могут заполнять кэш в соответствии с существующими правилами пути чтения |
| Прогрев кэша | Поведение не меняется |
| Packed File | Упакованные небольшие файлы Segment не кэшируются целиком; упакованные отдельные небольшие файлы индексов по-прежнему могут кэшироваться целиком |
При глобальной политике записи только индексов диапазоны footer и внутренних индексов Segment записываются в кэш посредством синхронного чтения и не управляются параметром enable_flush_file_cache_async. Отдельные файлы инвертированных индексов продолжают использовать существующий механизм прямой записи и асинхронного сброса.
Ограничение только результатов Compaction
Чтобы снизить нагрузку на кэш от результатов Compaction, не меняя активную запись в кэш при загрузке данных и Schema Change, задайте:
enable_file_cache=true
enable_file_cache_write_index_file_only=false
enable_file_cache_write_base_compaction_index_only=true
enable_file_cache_write_cumu_compaction_index_only=true
Cumulative Compaction по умолчанию записывает результаты в кэш, поэтому включение соответствующего параметра пропускает файлы Segment и сохраняет только отдельные файлы инвертированных индексов. Base Compaction по-прежнему сначала использует enable_file_cache_keep_base_compaction_output и долю попаданий в кэш для входных rowset, чтобы определить, нужно ли кэшировать результат. Параметр записи только индексов для Base Compaction ограничивает записываемое содержимое лишь после принятия этого решения.
Рекомендации
- Эти три параметра относятся к параметрам BE. Поддерживайте одинаковые значения на всех узлах BE одной вычислительной группы, чтобы узлы использовали единую политику записи в кэш.
- «Только индексы» не означает, что файловый кэш никогда не содержит данных Segment. Чтение страниц данных, отсутствующих в кэше, при выполнении запросов по-прежнему может заполнять кэш данными Segment.
- Эта политика может уменьшить засорение кэша при загрузке данных и Compaction, но сканирование большого объёма данных сразу после записи может увеличить число чтений из удалённого хранилища. Проверьте её производительность на рабочей нагрузке производственной среды и отслеживайте вытеснение из очереди Index и метрики чтения индексов в SQL Profile.
Настройка путей и размера кэша
file_cache_path Default: the storage directory under the BE deployment path
Этот параметр представляет собой массив JSON. Каждый элемент задаёт путь кэша и его атрибуты. Поддерживаются следующие поля:
| Поле | Описание |
|---|---|
path | Путь для хранения файлов кэша |
total_size | Общий размер кэша для этого пути (в байтах) |
ttl_percent | Доля пространства, выделенная очереди TTL, в процентах |
normal_percent | Доля пространства, выделенная очереди Normal, в процентах |
disposable_percent | Доля пространства, выделенная очереди Disposable, в процентах |
index_percent | Доля пространства, выделенная очереди Index, в процентах |
storage | Тип хранилища кэша: disk (по умолчанию) или memory |
Примеры конфигурации:
-
Конфигурация с одним путём:
[{"path":"/path/to/file_cache","total_size":21474836480}] -
Конфигурация с несколькими путями:
[{"path":"/path/to/file_cache","total_size":21474836480},{"path":"/path/to/file_cache2","total_size":21474836480}] -
Конфигурация хранения в памяти:
[{"path": "xxx", "total_size":53687091200, "storage": "memory"}]
Автоматическая очистка кэша
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
clear_file_cache | false | Определяет, нужно ли автоматически очищать кэшированные данные при перезапуске BE. При значении true кэш очищается при каждом перезапуске. |
Упреждающее вытеснение
Упреждающее вытеснение активно освобождает пространство, когда заполнение кэша достигает порогового значения. Это позволяет избежать запуска вытеснения во время выполнения запросов и связанных с ним колебаний производительности.
| Параметр | Значение по умолчанию | Описание |
|---|---|---|
enable_evict_file_cache_in_advance | true | Определяет, включено ли упреждающее вытеснение |
file_cache_enter_need_evict_cache_in_advance_percent | 88 | Порог заполнения (%) для запуска упреждающего вытеснения. Вытеснение начинается, когда занятое пространство кэша или число используемых inode достигает этой доли |
file_cache_exit_need_evict_cache_in_advance_percent | 85 | Порог заполнения (%) для остановки упреждающего вытеснения. Вытеснение прекращается, когда занятое пространство кэша снижается до этой доли |
Квота кэша
Doris предоставляет два независимых механизма управления файловым кэшем на уровне запроса. Выбирайте параметр в зависимости от того, нужно ли ограничить объём кэша, уже занятый запросом, или прекратить последующее заполнение кэша:
| Механизм управления | Основной параметр | Поведение после достижения ограничения | Сценарий использования |
|---|---|---|---|
| Ограничение доли занимаемого кэша | file_cache_query_limit_percent | Новые блоки по-прежнему могут записываться в кэш. BE сначала вытесняет блоки, учтённые для текущего запроса и доступные для освобождения, а затем при необходимости вытесняет данные из других очередей кэша | Ограничить объём кэша, занимаемый запросом, сохранив возможность дальнейшего заполнения кэша |
| Прекращение записи в кэш при удалённом сканировании по порогу в байтах | file_cache_query_limit_bytes | Если следующий блок кэша приведёт к превышению порога допущенного объёма в байтах, запрос на этом BE переходит в режим обращения только к удалённому хранилищу при промахе кэша. При последующих промахах данные читаются из удалённого хранилища без дальнейшей записи в файловый кэш | Ограничить запись в кэш и частую замену его содержимого при большом удалённом сканировании |
| Прекращение записи в кэш на фазе 2 отложенной материализации TopN | enable_topn_lazy_mat_phase2_no_write_file_cache | Поисковое чтение на фазе 2 отложенной материализации TopN при промахе кэша обращается только к удалённому хранилищу и не заполняет файловый кэш | Предотвратить засорение кэша поисковыми чтениями TopN с низкой вероятностью повторного использования |
Ограничение доли занимаемого кэша
Эта функция поддерживается начиная с версии 4.0.3.
Ограничение доли занимаемого кэша задаёт максимальный процент каждого экземпляра файлового кэша, который может использовать один запрос. Когда несколько пользователей или сложные запросы совместно используют ресурсы кэша, оно снижает риск того, что один большой запрос займёт слишком много кэша и вытеснит другие часто используемые данные.
Эта функция включает три уровня настройки: конфигурацию BE, конфигурацию FE и переменные сеанса.
Конфигурация BE
| Параметр | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
enable_file_cache_query_limit | Boolean | false | Главный переключатель ограничения кэша для запросов на стороне BE. BE обрабатывает переданный из FE параметр ограничения запроса только при включении этого переключателя |
Конфигурация FE
| Параметр | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
file_cache_query_limit_max_percent | Integer | 100 | Максимально допустимое значение квоты запроса, используемое для проверки верхней границы переменной сеанса |
Переменные сеанса
| Переменная | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
file_cache_query_limit_percent | Integer | -1 | При явном задании значение должно находиться в диапазоне [1, file_cache_query_limit_max_percent]. Оно определяет максимальный процент кэша, который может использовать один запрос. Рассчитанная квота должна быть не менее 256 MB; в противном случае BE записывает предупреждение в журнал |
Перед использованием этого механизма включите на BE оба параметра — enable_file_cache и enable_file_cache_query_limit, — и убедитесь, что в сеансе запроса enable_file_cache имеет значение true.
Пример использования
-- Limit a single query to using at most 50% of the cache
SET file_cache_query_limit_percent = 50;
-- Execute the query
SELECT * FROM large_table;
При последующих промахах кэша запись в файловый кэш по-прежнему допускается. Когда объём кэша, занимаемый запросом, превышает квоту, BE освобождает пространство с помощью записей LRU на уровне запроса и других очередей кэша. Этот механизм не переводит запрос в режим запрета дальнейшей записи.
Прекращение записи в кэш при удалённом сканировании по порогу в байтах
Эта функция поддерживается только в Doris 4.1.x. В Doris 4.0.x она не поддерживается.
file_cache_query_limit_bytes ограничивает суммарный объём в байтах, допущенный к записи в файловый кэш при сквозном чтении из-за промахов кэша во время удалённого сканирования для одного запроса SELECT на каждом BE. Параметр действует только в режиме с разделением вычислений и хранения, когда на BE задано enable_file_cache=true. Он не зависит от enable_file_cache_query_limit или file_cache_query_limit_max_percent.
Параллельные сканеры одного запроса совместно используют один порог на BE, но этот порог не является общим для всего запроса или кластера. Например, если запрос выполняется на 10 узлах BE с порогом 1 GiB, каждый BE может независимо допустить примерно 1 GiB; ограничение не составляет 1 GiB для всех BE вместе.
Параметры
| Параметр | Расположение | Тип | Значение по умолчанию | Обязательный | Описание |
|---|---|---|---|---|---|
file_cache_query_limit_bytes | Переменная сеанса | BigInt | -1 | Да | Порог заполнения кэша при удалённом сканировании для одного запроса на каждом BE, в байтах. Значение меньше 0 отключает этот механизм; 0 отключает заполнение кэша с начала выполнения запроса; при положительном значении допущенный объём накапливается по блокам кэша |
enable_file_cache_query_limit_segment_meta | Конфигурация BE | Boolean | false | Нет | Определяет, учитывается ли запись footer и метаданных Segment в кэш в том же пороге в байтах. Этот параметр можно настраивать динамически. Запись страниц данных и инвертированных индексов подпадает под порог в байтах всегда, когда этот механизм активен |
file_cache_query_limit_bytes действует следующим образом:
| Значение | Поведение |
|---|---|
< 0 | Отключает этот механизм и сохраняет исходное поведение заполнения кэша при промахах |
= 0 | С начала выполнения переводит запрос на каждом BE в режим обращения только к удалённому хранилищу при промахе кэша. Запрошенный диапазон, полностью покрытый локальным кэшем, по-прежнему может читаться локально; диапазон, покрытый не полностью, читается напрямую из удалённого хранилища без заполнения кэша |
> 0 | Допускает блоки кэша, пока их суммарный допущенный объём в байтах не превышает порог. Когда следующий блок привёл бы к его превышению, этот блок отклоняется, а последующие промахи для запроса на этом BE больше не заполняют кэш |
Допуск оценивается по блокам кэша, поэтому фактический объём записи не обязательно равен порогу. Если оставшийся бюджет меньше следующего блока кэша, весь блок пропускается, а оставшийся бюджет не используется для меньших блоков, появляющихся позже. После перехода запроса на BE в режим обращения только к удалённому хранилищу при промахе кэша заполнение кэша на этом BE не возобновляется.
Ограничение заполнения кэша при удалённом сканировании
В следующем примере предполагается, что large_table находится в кластере с разделением вычислений и хранения и на каждом BE включён файловый кэш. Пример допускает до 1 GiB блоков кэша от удалённого сканирования на каждом BE:
SET enable_profile = true;
SET profile_level = 2;
SET file_cache_query_limit_bytes = 1073741824;
SELECT COUNT(*) FROM large_table;
Результат запроса не меняется. Когда следующий блок кэша на BE привёл бы к превышению допущенного объёма в 1 GiB, при последующих промахах кэша для этого запроса на том же BE данные читаются из удалённого хранилища без дополнительной записи в локальный кэш.
Чтобы разовое сканирование не заполняло файловый кэш с самого начала, задайте порог 0, а после запроса восстановите значение по умолчанию:
SET file_cache_query_limit_bytes = 0;
SELECT COUNT(*) FROM large_table;
SET file_cache_query_limit_bytes = -1;
Учитываются ли метаданные Segment
По умолчанию запись в кэш страниц данных и инвертированных индексов учитывается в пороге, а запись footer и метаданных Segment — нет. Поэтому footer и метаданные Segment могут по-прежнему записываться после перехода запроса в режим обращения только к удалённому хранилищу при промахе кэша, а общий объём записи, показанный в Profile, может превышать file_cache_query_limit_bytes.
Чтобы также прекратить заполнение кэша footer и метаданными Segment, задайте следующую настройку на каждом BE одной вычислительной группы:
enable_file_cache_query_limit_segment_meta=true
Этот параметр можно изменить немедленно через API динамической конфигурации BE. Чтобы сохранить его после перезапуска, добавьте его в be.conf или используйте постоянную динамическую конфигурацию. Подробнее см. в разделе Конфигурация BE.
Проверка с помощью Query Profile
После включения Query Profile проверьте группу метрик FileCache в узле Scanner:
| Метрика | Описание |
|---|---|
RemoteOnlyOnMissTriggered | Значение 1 означает, что Scanner зафиксировал переход запроса в режим обращения только к удалённому хранилищу при промахе кэша |
RemoteOnlyOnMissThresholdBytes | Порог в байтах, заданный для запроса |
BytesWriteIntoCache | Общее количество байтов, фактически записанных в файловый кэш |
InvertedIndexBytesWriteIntoCache | Количество байтов инвертированных индексов, фактически записанных в файловый кэш |
SegmentFooterIndexBytesWriteIntoCache | Количество байтов footer и метаданных Segment, фактически записанных в файловый кэш |
NumSkipCacheIOTotal | Количество операций ввода-вывода, обошедших кэш. Эта метрика также может включать операции ввода-вывода, для которых кэш был пропущен другими политиками, поэтому оценивайте её вместе с RemoteOnlyOnMissTriggered |
Если допущенный объём в байтах в точности равен порогу и до завершения запроса ни один последующий блок кэша не пытается его превысить, RemoteOnlyOnMissTriggered может остаться равным 0. Состояние меняется только тогда, когда очередной блок привёл бы к превышению порога.
Рекомендации и особенности
- Для разовых полных сканирований, ETL с низкой вероятностью повторного использования данных или разовых нерегламентированных запросов используйте небольшой положительный порог либо
0, чтобы отключить заполнение кэша с самого начала и избежать замены часто используемых данных редко используемыми. - Этот параметр ограничивает заполнение файлового кэша после промахов при чтении запросом. Он не ограничивает объём чтения из удалённого хранилища, не завершает запрос и не влияет на запись в кэш при загрузке данных, Compaction, Schema Change или явном прогреве кэша.
- В режиме обращения только к удалённому хранилищу при промахе кэша запрошенные диапазоны, полностью покрытые локальным кэшем, по-прежнему могут читаться локально. Диапазоны, покрытые не полностью, читаются напрямую из удалённого хранилища, что может увеличить объём ввода-вывода объектного хранилища и задержку запросов.
- Используйте
file_cache_query_limit_percent, если требуется ограничить объём кэша, удерживаемый запросом, сохранив возможность заполнения кэша при последующих промахах. Используйтеfile_cache_query_limit_bytes, если требуется прекратить дальнейшее заполнение после допуска заданного объёма данных. - Исключение footer и метаданных Segment по умолчанию сохраняет преимущества кэширования метаданных, которые часто используются повторно. Включайте
enable_file_cache_query_limit_segment_meta, только если запись этих данных также должна прекращаться после достижения порога, и проверяйте результат с помощью Query Profile.
Прекращение записи в кэш на фазе 2 отложенной материализации TopN
Эта функция поддерживается начиная с версии 4.0.8.
Запросы с ORDER BY ... LIMIT используют отложенную материализацию TopN: фаза 1 читает только столбцы сортировки для выбора строк-кандидатов, а фаза 2 получает остальные столбцы по идентификатору строки. Чтения на фазе 2 разрежены и редко используются повторно, поэтому заполнение ими файлового кэша в режиме с разделением вычислений и хранения легко вытесняет часто используемые данные.
| Переменная | Тип | Значение по умолчанию | Описание |
|---|---|---|---|
enable_topn_lazy_mat_phase2_no_write_file_cache | Boolean | false | При включении чтения на фазе 2 отложенной материализации TopN в случае промаха файлового кэша обращаются напрямую к удалённому хранилищу и не записывают этот диапазон в файловый кэш |
Пример использования
SET enable_topn_lazy_mat_phase2_no_write_file_cache = true;
SELECT * FROM large_table ORDER BY create_time DESC LIMIT 100;
Примечания
- Переменная действует только в режиме с разделением вычислений и хранения; её установка в режиме с совмещёнными вычислениями и хранением не даёт эффекта.
- Она влияет только на поисковые чтения фазы 2 отложенной материализации TopN. Чтение столбцов сортировки на фазе 1, заполнение кэша другими запросами и запись в кэш при загрузке данных, Compaction и прогреве кэша не меняются.
- Диапазоны, которые фаза 2 находит в файловом кэше, по-прежнему читаются локально. Отсутствующие в кэше диапазоны читаются напрямую из удалённого хранилища, что может увеличить объём ввода-вывода объектного хранилища.
- Если запросы TopN регулярно обращаются к одним и тем же часто используемым строкам, отключение заполнения кэша может увеличить число удалённых чтений. Оценивайте эффект с учётом характера ваших запросов.
Прогрев кэша
Doris предоставляет функцию прогрева кэша, позволяющую заранее загружать данные из удалённого хранилища в локальный кэш. Поддерживаются следующие три режима прогрева:
| Режим | Описание |
|---|---|
| Прогрев между вычислительными группами | Прогревает кэш часто используемых данных вычислительной группы A в вычислительной группе B. Doris периодически собирает сведения о наиболее часто используемых таблицах и партициях каждой вычислительной группы и на их основе выполняет выборочный прогрев |
| Прогрев данных таблицы | Загружает все данные указанной таблицы в целевую вычислительную группу |
| Прогрев данных партиции | Загружает данные определённой партиции указанной таблицы в целевую вычислительную группу |
Подробные сведения об использовании см. в документации SQL WARM-UP.
Прогрев кэша заранее загружает данные из удалённого хранилища. Чтение из кэша других BE дополняет его во время выполнения запросов: при промахе локального кэша блок сначала читается из другого BE и только при его отсутствии на всех BE — из удалённого хранилища. Это покрывает чтения данных, не попавших в кэш при прогреве.
Очистка кэша
Doris предоставляет синхронный и асинхронный способы очистки кэша:
| Способ | Команда | Описание |
|---|---|---|
| Синхронная очистка | curl 'http://BE_IP:WEB_PORT/api/file_cache?op=clear&sync=true' | Команда возвращает управление только после завершения очистки. Doris синхронно удаляет файлы кэша из локальной файловой системы и очищает метаданные в памяти. Это быстро освобождает пространство, но может повлиять на выполняющиеся запросы. Обычно используется для быстрого тестирования |
| Асинхронная очистка | curl 'http://BE_IP:WEB_PORT/api/file_cache?op=clear&sync=false' | Команда возвращает управление немедленно; очистка выполняется асинхронно, и можно наблюдать постепенное уменьшение занятого кэшем пространства. Doris обходит метаданные в памяти и удаляет файлы кэша по одному, откладывая удаление файлов, которые сейчас используются. Этот способ меньше влияет на выполняющиеся запросы, но полная очистка занимает больше времени |
Мониторинг кэша
Сведения о блоках кэша
Начиная с Doris 4.1 можно запрашивать information_schema.file_cache_info, чтобы просматривать записи кэша на уровне блоков и суммировать занятое кэшем пространство по tablet, BE, пути или типу кэша. Doris 4.0.x не поддерживает эту системную таблицу.
Сведения о наиболее часто используемых данных
Doris собирает сведения о наиболее часто используемых данных кэша для каждой вычислительной группы каждые 10 минут и записывает их во внутреннюю системную таблицу __internal_schema.cloud_cache_hotspot. Следующие запросы позволяют анализировать часто используемые данные для планирования кэша.
До версии 3.0.4 для получения сведений о наиболее часто используемых данных кэша можно было применять оператор SHOW CACHE HOTSPOT. Начиная с версии 3.0.4 этот оператор больше не поддерживается. Вместо него обращайтесь напрямую к системной таблице __internal_schema.cloud_cache_hotspot.
Просмотр наиболее часто используемых таблиц во всех вычислительных группах
-- Equivalent to SHOW CACHE HOTSPOT "/" before version 3.0.4
WITH t1 AS (
SELECT
cluster_id,
cluster_name,
table_id,
table_name,
insert_day,
SUM(query_per_day) AS query_per_day_total,
SUM(query_per_week) AS query_per_week_total
FROM __internal_schema.cloud_cache_hotspot
GROUP BY cluster_id, cluster_name, table_id, table_name, insert_day
)
SELECT
cluster_id AS ComputeGroupId,
cluster_name AS ComputeGroupName,
table_id AS TableId,
table_name AS TableName
FROM (
SELECT
ROW_NUMBER() OVER (
PARTITION BY cluster_id
ORDER BY insert_day DESC, query_per_day_total DESC, query_per_week_total DESC
) AS dr2,
*
FROM t1
) t2
WHERE dr2 = 1;
Просмотр наиболее часто используемых таблиц в определённой вычислительной группе
Замените cluster_name = "compute_group_name0" на фактическое имя вычислительной группы.
-- Equivalent to SHOW CACHE HOTSPOT '/compute_group_name0' before version 3.0.4
WITH t1 AS (
SELECT
cluster_id,
cluster_name,
table_id,
table_name,
insert_day,
SUM(query_per_day) AS query_per_day_total,
SUM(query_per_week) AS query_per_week_total
FROM __internal_schema.cloud_cache_hotspot
WHERE cluster_name = "compute_group_name0" -- Replace with the actual compute group name, e.g. "default_compute_group"
GROUP BY cluster_id, cluster_name, table_id, table_name, insert_day
)
SELECT
cluster_id AS ComputeGroupId,
cluster_name AS ComputeGroupName,
table_id AS TableId,
table_name AS TableName
FROM (
SELECT
ROW_NUMBER() OVER (
PARTITION BY cluster_id
ORDER BY insert_day DESC, query_per_day_total DESC, query_per_week_total DESC
) AS dr2,
*
FROM t1
) t2
WHERE dr2 = 1;
Метрики пространства кэша и доли попаданий
Используйте следующую конечную точку для получения статистики кэша узла BE (brpc_port по умолчанию равен 8060):
curl {be_ip}:{brpc_port}/vars
Имена возвращаемых метрик имеют префикс, соответствующий пути на диске. Например, префикс _mnt_disk1_gavinchou_debug_doris_cloud_be0_storage_file_cache_ соответствует пути /mnt/disk1/gavinchou/debug/doris-cloud/be0_storage_file_cache/. После удаления префикса пути метрики имеют следующие значения (все размеры указаны в байтах):
| Имя метрики (без префикса пути) | Описание |
|---|---|
file_cache_cache_size | Текущий общий размер файлового кэша |
file_cache_disposable_queue_cache_size | Текущий размер очереди Disposable |
file_cache_disposable_queue_element_count | Текущее количество элементов в очереди Disposable |
file_cache_disposable_queue_evict_size | Суммарный объём данных, вытесненных из очереди Disposable с момента запуска |
file_cache_index_queue_cache_size | Текущий размер очереди Index |
file_cache_index_queue_element_count | Текущее количество элементов в очереди Index |
file_cache_index_queue_evict_size | Суммарный объём данных, вытесненных из очереди Index с момента запуска |
file_cache_normal_queue_cache_size | Текущий размер очереди Normal |
file_cache_normal_queue_element_count | Текущее количество элементов в очереди Normal |
file_cache_normal_queue_evict_size | Суммарный объём данных, вытесненных из очереди Normal с момента запуска |
file_cache_total_evict_size | Суммарный объём данных, вытесненных из всего файлового кэша с момента запуска |
file_cache_ttl_cache_evict_size | Суммарный объём данных, вытесненных из очереди TTL с момента запуска |
file_cache_ttl_cache_lru_queue_element_count | Текущее количество элементов в очереди TTL |
file_cache_ttl_cache_size | Текущий размер очереди TTL |
file_cache_evict_by_heat_[A]_to_[B] | Объём данных кэша типа A, вытесненных для освобождения места под данные кэша типа B (вытеснение по времени истечения срока действия) |
file_cache_evict_by_size_[A]_to_[B] | Объём данных кэша типа A, вытесненных для освобождения места под данные кэша типа B (вытеснение по размеру) |
file_cache_evict_by_self_lru_[A] | Объём данных кэша типа A, которые очередь типа A вытеснила из себя для записи новых данных (вытеснение на основе LRU) |
file_cache_evict_not_downloaded_size | Добавлена в 4.1.5. Суммарный логический размер диапазонов в байтах для блоков, удалённых до завершения загрузки, за исключением блоков, загружаемых в данный момент; не отражает физическое вытеснение загруженных данных |
file_cache_evict_not_downloaded_num | Добавлена в 4.1.5. Суммарное количество таких удалённых блоков |
file_cache_ttl_mgr_ttl_info_map_size | Добавлена в 4.1.5. Текущее количество отслеживаемых записей со сведениями о TTL для tablet, а не блоков |
Начиная с версии 4.1.5 общие и отдельные для каждой очереди счётчики вытесненных байтов учитывают только полностью загруженные блоки. Блоки, удалённые до завершения загрузки, учитываются отдельно новыми счётчиками; блоки, помеченные для удаления во время загрузки, не увеличивают эти счётчики удаления. Соответствующие имена метрик в системной таблице SQL — evict_not_downloaded_size и evict_not_downloaded_num. См. file_cache_statistics.
Метрики кэша в SQL Profile
Метрики кэша в SQL Profile находятся в узле SegmentIterator:
| Имя метрики | Описание |
|---|---|
BytesScannedFromCache | Объём данных, прочитанных из файлового кэша |
BytesScannedFromRemote | Объём данных, прочитанных из удалённого хранилища |
BytesWriteIntoCache | Объём данных, записанных в файловый кэш |
LocalIOUseTimer | Время, затраченное на чтение из файлового кэша |
NumLocalIOTotal | Количество операций чтения из файлового кэша |
NumRemoteIOTotal | Количество операций чтения из удалённого хранилища |
NumSkipCacheIOTotal | Количество операций чтения из удалённого хранилища без записи в файловый кэш |
RemoteIOUseTimer | Время, затраченное на чтение из удалённого хранилища |
WriteCacheIOUseTimer | Время, затраченное на запись в файловый кэш |
После включения записи в кэш только индексов отслеживайте следующие метрики по категориям, чтобы определить, читаются ли отдельные инвертированные индексы, footer и внутренние индексы Segment из кэша:
| Метрика | Описание |
|---|---|
InvertedIndexBytesScannedFromCache / InvertedIndexBytesScannedFromRemote | Объём данных отдельных инвертированных индексов, прочитанных из файлового кэша / удалённого хранилища |
InvertedIndexNumLocalIOTotal / InvertedIndexNumRemoteIOTotal | Количество локальных / удалённых чтений для отдельных инвертированных индексов |
InvertedIndexLocalIOUseTimer / InvertedIndexRemoteIOUseTimer | Время, затраченное на локальное / удалённое чтение отдельных инвертированных индексов |
SegmentFooterIndexBytesScannedFromCache / SegmentFooterIndexBytesScannedFromRemote | Объём данных footer и внутренних индексов Segment, прочитанных из файлового кэша / удалённого хранилища |
SegmentFooterIndexNumLocalIOTotal / SegmentFooterIndexNumRemoteIOTotal | Количество локальных / удалённых чтений для footer и внутренних индексов Segment |
SegmentFooterIndexLocalIOUseTimer / SegmentFooterIndexRemoteIOUseTimer | Время, затраченное на локальное / удалённое чтение footer и внутренних индексов Segment |
Полный отчёт о производительности запроса можно просмотреть с помощью раздела Анализ производительности запросов.
NumPeerIOTotal, PeerIOUseTimer, SameCGPeerIOTotal, CrossCGPeerIOTotal и связанные счётчики показывают, были ли данные получены из кэша другого BE (чтение из кэша других BE). См. Чтение из кэша других BE: счётчики Query Profile.
Политика кэширования TTL
Политика кэширования TTL (Time-To-Live, время жизни) позволяет задать срок хранения в кэше данных определённых таблиц. Это обеспечивает достаточно долгое сохранение в кэше небольших часто используемых таблиц или недавно загруженных данных, предотвращая их вытеснение логикой LRU, запускаемой большими запросами.
Установка TTL при создании таблицы
Задайте file_cache_ttl_seconds (в секундах) в предложении PROPERTIES оператора CREATE TABLE:
CREATE TABLE IF NOT EXISTS customer (
C_CUSTKEY INTEGER NOT NULL,
C_NAME VARCHAR(25) NOT NULL,
C_ADDRESS VARCHAR(40) NOT NULL,
C_NATIONKEY INTEGER NOT NULL,
C_PHONE CHAR(15) NOT NULL,
C_ACCTBAL DECIMAL(15,2) NOT NULL,
C_MKTSEGMENT CHAR(10) NOT NULL,
C_COMMENT VARCHAR(117) NOT NULL
)
DUPLICATE KEY(C_CUSTKEY, C_NAME)
DISTRIBUTED BY HASH(C_CUSTKEY) BUCKETS 32
PROPERTIES (
"file_cache_ttl_seconds" = "300"
);
Начиная с версии 4.1.5 все пути записи и чтения рассчитывают абсолютный срок окончания защиты как tablet creation time + file_cache_ttl_seconds. В приведённом выше примере каждый tablet защищён в течение 300 секунд после своего создания. Последующая загрузка данных, чтение, Compaction, Schema Change и прогрев не перезапускают таймер. После истечения срока данные кэшируются обычным образом; каждая новая загрузка данных не гарантирует ещё 300 секунд защиты.
Допустимый диапазон для file_cache_ttl_seconds — 0 <= value <= 4611686018427387903 (то есть Long.MAX_VALUE / 2). Начиная с версии 4.1.4 операторы CREATE TABLE и ALTER TABLE ... SET проверяют это значение, и значение вне диапазона или в неверном формате отклоняется с ошибкой:
The value <v> formats error or is out of range (0 <= integer <= 4611686018427387903). Larger values may overflow in BE and change TTL cache to normal cache; please use 4611686018427387903 or a smaller value.
До 4.1.4 верхняя граница не проверялась, и слишком большое значение приводило к переполнению на стороне BE, переводя кэш TTL в обычный кэш.
Изменение настройки TTL для таблицы
ALTER TABLE customer SET ("file_cache_ttl_seconds" = "3000");
Изменения TTL вступают в силу с задержкой, необходимой для синхронизации метаданных. Если TTL не был задан при создании таблицы, его можно добавить с помощью ALTER TABLE. Новый срок окончания защиты по-прежнему рассчитывается от времени создания tablet. Начиная с версии 4.1.5 продление истёкшего TTL до будущего срока также возвращает обычные кэшированные блоки в очередь TTL. Установка TTL в 0 возвращает их к обычному кэшированию.
Практический пример
Описание сценария:
У пользователя есть набор таблиц с общим объёмом данных более 3 TB, но доступная ёмкость кэша составляет лишь 1.2 TB. Среди этих таблиц две используются часто:
| Таблица | Размер | Характер обращений |
|---|---|---|
dimension_table | 200 MB | Частые обращения; данные меняются редко |
fact_table | 100 GB | Новые данные загружаются ежедневно и должны быть доступны для запросов по схеме T+1 |
К другим большим таблицам обращаются редко.
Проблема: при стандартной политике LRU запросы к большим таблицам могут вытеснять данные dimension_table из кэша, вызывая колебания производительности запросов к таблице измерений.
Решение: задайте TTL для обеих часто используемых таблиц, чтобы обеспечить достаточно долгое хранение их данных в кэше.
-- Dimension table: protect each tablet until 1 year after creation; use a longer TTL if it is already older than 1 year
ALTER TABLE dimension_table SET ("file_cache_ttl_seconds" = "31536000");
-- Fact table with new daily partitions: protect each new partition's tablets until 1 day after creation
ALTER TABLE fact_table SET ("file_cache_ttl_seconds" = "86400");
Часто задаваемые вопросы
Вопрос: доля попаданий в кэш низкая, и запросы по-прежнему выполняются медленно. Как найти причину?
- Используйте
curl {be_ip}:{brpc_port}/vars, чтобы проверить метрикиevict_sizeдля каждой очереди и определить, происходит ли частое вытеснение. - Проверьте соотношение
BytesScannedFromRemoteиBytesScannedFromCacheв SQL Profile, чтобы определить фактическую долю попаданий. - Если большие запросы часто вытесняют часто используемые данные, рассмотрите возможность включения функции ограничения кэша для запросов (
enable_file_cache_query_limit) или настройки политики TTL для часто используемых таблиц.
Вопрос: данные кэша теряются после перезапуска BE.
Проверьте, не задано ли для clear_file_cache значение true. Если очищать кэш при перезапуске не требуется, задайте false (значение по умолчанию).
Вопрос: первый запрос после ввода новой вычислительной группы в эксплуатацию выполняется очень медленно.
Используйте функцию прогрева кэша, чтобы до поступления запросов заранее загрузить часто используемые данные таблиц или партиций из удалённого хранилища в локальный кэш новой вычислительной группы. Подробные сведения об использовании см. в документации SQL WARM-UP. Если другая вычислительная группа уже содержит эти данные в своём кэше, включённое чтение из кэша других BE позволяет новой вычислительной группе при промахе читать их из BE этой группы.
Вопрос: как определить, заполнено ли доступное пространство кэша?
Сравните метрику file_cache_cache_size со значением total_size, заданным в file_cache_path. Если размер приближается к пределу, проверьте, нужно ли увеличить ёмкость или изменить процентные доли пространства, выделенные каждой очереди.