Построчное хранение
Row Store — это возможность Doris, которая дополняет колоночное хранение компактной двоичной копией каждой строки в построчном формате. При точечных запросах она позволяет заменить «одну операцию IO на каждый столбец» на «одну операцию IO для чтения всей строки». Эта возможность поддерживается начиная с Doris 2.0.0.
По умолчанию Doris использует колоночное хранение, при котором данные каждого столбца хранятся непрерывно. Колоночное хранение хорошо подходит для аналитических сценариев (агрегации, фильтрации, сортировки и так далее), поскольку позволяет читать только необходимые столбцы. Однако при точечных запросах (например, SELECT *) требуется прочитать все столбцы, выполнив по одной операции IO для каждого из них. В широких таблицах с большим количеством столбцов (например, сотнями) IOPS становится узким местом.
Когда построчное хранение включено, система при записи сохраняет дополнительный столбец, объединяя все столбцы строки в компактном двоичном формате. После этого точечному запросу достаточно одной операции IO для чтения всех данных строки, что существенно снижает IOPS и задержку запросов.
Сценарии применения
Построчное хранение предназначено прежде всего для следующих двух категорий запросов. Таблица ниже поможет быстро определить, стоит ли его включать:
| Сценарий | Типичный шаблон запроса | Требования к модели таблицы | Рекомендация |
|---|---|---|---|
| Точечные запросы по первичному ключу с высокой конкурентностью | SELECT ... FROM t WHERE pk1 = ? AND pk2 = ? | Таблица Unique Key MOW | Рекомендуется |
| TOPN-запросы к широким таблицам | SELECT * FROM t [WHERE ...] ORDER BY ... LIMIT N | Таблица Duplicate / таблица Unique Key MOW | Рекомендуется |
| Аналитические запросы | Агрегация, сложная фильтрация по небольшому числу столбцов и так далее | — | Не рекомендуется (достаточно колоночного хранения) |
В следующих разделах описаны условия активации, способы создания таблиц и примеры запросов для каждого сценария.
Сценарий 1: точечные запросы по первичному ключу с высокой конкурентностью
Этот сценарий подходит для запросов с высокой конкурентностью к таблицам Unique Key MOW, в которых поиск конкретных строк выполняется по полному первичному ключу. При соблюдении условий запрос выполняется по пути Short-Circuit, минуя стандартный конвейер выполнения.
Условия активации
Все следующие условия должны выполняться одновременно:
- Таблица использует модель Unique Key MOW (
"enable_unique_key_merge_on_write" = "true"). - Построчное хранение включено с помощью
"store_row_column" = "true"или"row_store_columns" = "...". - Предложение
WHEREсодержит условия равенства для всех столбцов первичного ключа, соединённые операторомAND.
Пример создания таблицы
В следующем примере создаётся таблица с 8 столбцами, построчное хранение включается только для 5 из них, а параметру page_size задаётся значение 4 KB для достижения наилучшей производительности точечных запросов:
CREATE TABLE `tbl_point_query` (
`k` int(11) NULL,
`v1` decimal(27, 9) NULL,
`v2` varchar(30) NULL,
`v3` varchar(30) NULL,
`v4` date NULL,
`v5` datetime NULL,
`v6` float NULL,
`v7` datev2 NULL
) ENGINE=OLAP
UNIQUE KEY(`k`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`k`) BUCKETS 1
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"light_schema_change" = "true",
"row_store_columns" = "k,v1,v3,v5,v7",
"row_store_page_size" = "4096"
);
Пример запроса
-- Query all columns
SELECT * FROM tbl_point_query WHERE k = 100;
-- Query a subset of columns
SELECT k, v1, v3, v5, v7 FROM tbl_point_query WHERE k = 100;
Построчное хранение части столбцов: если построчно хранится только часть столбцов (например, v1), а запрос обращается к столбцу, который не хранится построчно (например, v2), Doris читает недостающий столбец из колоночного хранилища. Столбцы, хранящиеся построчно, по-прежнему читаются эффективно, а для остальных выполняются обычные операции IO колоночного хранения.
Способ проверки
Выполните EXPLAIN для запроса. В выводе должен присутствовать маркер SHORT-CIRCUIT. Подробнее см. в разделе Точечные запросы с высокой конкурентностью.
Сценарий 2: TOPN-запросы с отложенной материализацией
Этот сценарий подходит для запросов SELECT * к широким таблицам Duplicate или Unique Key MOW, которые «сортируют данные, а затем выбирают небольшое количество строк». При соблюдении условий запрос выполняется по пути Fetch Row Store и в сочетании с двухфазной оптимизацией TOPN извлекает только строки, фактически попавшие в результат.
Условия активации
Все следующие условия должны выполняться одновременно:
- Таблица использует модель Duplicate или Unique Key MOW (
"enable_unique_key_merge_on_write" = "true"). - Построчное хранение должно быть включено для всех столбцов (
"store_row_column" = "true"). - Запрос соответствует шаблону
SELECT * FROM tbl [WHERE ...] ORDER BY ... LIMIT N. - Запрос должен использовать
SELECT *; выбор отдельных столбцов не поддерживается. - Должна сработать оптимизация отложенной материализации TOPN. Подробнее см. в разделе Оптимизация TOPN-запросов.
Пример создания таблицы
CREATE TABLE `tbl_duplicate` (
`k` int(11) NULL,
`v1` string NULL
) ENGINE=OLAP
DUPLICATE KEY(`k`)
COMMENT 'OLAP'
DISTRIBUTED BY HASH(`k`) BUCKETS 1
PROPERTIES (
"light_schema_change" = "true",
"store_row_column" = "true",
"row_store_page_size" = "4096"
);
Для таблиц Duplicate необходимо задать "store_row_column" = "true"; указание части столбцов через row_store_columns не поддерживается. Все столбцы хранятся построчно.
Пример запроса
SELECT * FROM tbl_duplicate WHERE k < 10 ORDER BY k LIMIT 10;
Способ проверки
Выполните EXPLAIN для запроса. В выводе должны присутствовать оба маркера: FETCH ROW STORE и OPT TWO PHASE.
Параметры конфигурации
Задайте следующие параметры в PROPERTIES при выполнении CREATE TABLE:
| Параметр | Значение по умолчанию | Поддерживаемые версии | Описание |
|---|---|---|---|
store_row_column | false | 2.0+ | При значении true включает построчное хранение для всех столбцов. |
row_store_columns | Все столбцы | 3.0+ | Включает построчное хранение только для указанных столбцов, перечисленных в формате "col1,col2,...". При задании этого параметра неявно включается store_row_column. По сравнению с построчным хранением всех столбцов это позволяет существенно снизить дополнительные затраты на хранение. |
row_store_page_size | 16384 (16 KB) | 2.0+ | Размер страницы построчного хранения в байтах. Страница — минимальная единица IO: даже чтение одной строки требует операции IO объёмом в одну страницу. |
Рекомендации по настройке row_store_page_size
row_store_page_size напрямую влияет на соотношение между производительностью точечных запросов и дополнительными затратами на хранение:
| Цель оптимизации | Рекомендуемое значение | Компромисс |
|---|---|---|
| Наилучшая производительность точечных запросов | 4096 (4 KB) или меньше | Более высокие дополнительные затраты на хранение |
| Сбалансированный вариант (по умолчанию) | 16384 (16 KB) | — |
| Минимальные дополнительные затраты на хранение | 65536 (64 KB) или больше | Более высокая задержка точечных запросов |
Примечания
- Дополнительные затраты на хранение: включение построчного хранения увеличивает использование дискового пространства. В зависимости от характеристик данных объём дополнительного хранения обычно составляет от 2 до 10 исходных размеров таблицы. Проверьте влияние на реальных данных.
- Влияние
page_sizeна объём хранения: меньшее значениеrow_store_page_sizeповышает производительность точечных запросов, но увеличивает дополнительные затраты на хранение. Рекомендации по настройке приведены в разделе Параметры конфигурации. - ALTER не поддерживается: изменение свойств
store_row_columnиrow_store_columnsс помощьюALTER TABLEне поддерживается.