Перейти к содержимому
Последнее обновление

Рекомендации по использованию моделей таблиц

В этом документе рассматриваются особенности использования моделей данных Doris: выбор модели, проектирование схемы таблицы и ограничения моделей. Он поможет выбрать подходящую модель и избежать распространённых проблем с производительностью.

Рекомендации по выбору модели данных​

Модель данных определяется при создании таблицы, и изменить её нельзя. Поэтому выбор подходящей модели данных имеет решающее значение.

Сравнение трёх моделей​

Модель данныхСценарии использованияПреимуществаПримечания
DuplicateПроизвольные запросы по любым измерениямНет ограничений агрегационной модели; полностью используются преимущества столбцового хранения (читаются только необходимые столбцы)Предварительная агрегация недоступна (но поддерживается через асинхронные материализованные представления)
UniqueТребуется уникальность первичного ключа и обновление данныхГарантирует уникальность первичного ключа; поддерживает гибкое обновление данныхПредварительная агрегация недоступна (но поддерживается через асинхронные материализованные представления)
AggregateОтчётные запросы с фиксированными шаблонамиПредварительная агрегация значительно сокращает объём данных, сканируемых и обрабатываемых при выполнении запросаЗапросы count(*) неэффективны; при выполнении запросов с типом агрегации, отличным от объявленного, необходимо учитывать корректность семантики

Требования к частичному обновлению столбцов​

Если вашим бизнес-процессам необходимо частичное обновление столбцов, рекомендации по его использованию приведены в следующих документах:

Рекомендации по типам столбцов при создании таблиц​

При создании таблицы соблюдайте следующие правила выбора типов и порядка столбцов:

  1. Порядок столбцов: столбцы Key должны располагаться перед всеми столбцами Value.
  2. Предпочитайте целочисленные типы: используйте целочисленные типы везде, где это возможно, поскольку вычисления и поиск по целым числам значительно эффективнее, чем по строкам.
  3. Используйте минимальный достаточный размер целочисленного типа: при выборе между целочисленными типами разного размера руководствуйтесь принципом «ровно столько, сколько нужно».
  4. Используйте минимальную достаточную длину строки переменной длины: для типов VARCHAR и STRING придерживайтесь того же принципа «ровно столько, сколько нужно» при выборе длины.

Различия в семантике столбцов Key между моделями​

В моделях Duplicate, Aggregate и Unique столбцы Key задаются при создании таблицы, но их семантика различается:

МодельРоль столбцов Key
DuplicateИспользуются только как «столбцы сортировки»; не обеспечивают уникальную идентификацию
Aggregate, UniqueИспользуются и как «столбцы сортировки», и как «столбцы уникальной идентификации»; это столбцы Key в полном смысле слова

Ограничения модели Aggregate​

Модель Aggregate предоставляет пользователям итоговые агрегированные данные. Иными словами, любые данные, которые ещё не были агрегированы (например, данные из двух разных пакетов загрузки), должны быть приведены к согласованному состоянию с помощью определённого механизма, прежде чем они станут доступны пользователям.

Пример обеспечения согласованности​

Предположим, что таблица имеет следующую схему:

Имя столбцаТипТип агрегацииКомментарий
user_idLARGEINTИдентификатор пользователя
dateDATEДата загрузки данных
costBIGINTSUMОбщие расходы пользователя

В движке хранения уже содержатся данные из двух пакетов загрузки:

пакет 1

user_iddatecost
100012017/11/2050
100022017/11/2139

пакет 2

user_iddatecost
100012017/11/201
100012017/11/215
100032017/11/2222

Как видно, данные пользователя 10001 из двух пакетов загрузки ещё не агрегированы. Чтобы пользователи видели только итоговые агрегированные данные, приведённые ниже:

user_iddatecost
100012017/11/2051
100012017/11/215
100022017/11/2139
100032017/11/2222

Doris добавляет оператор агрегации в движок выполнения запросов, обеспечивая согласованность данных, доступных пользователям.

Семантическая ловушка в запросах с другим типом агрегации​

При выполнении запроса агрегации по столбцу Value с типом агрегации, отличным от объявленного, необходимо учитывать семантику. Например:

SELECT MIN(cost) FROM table;

Результатом будет 5, а не 1.

Затраты на выполнение запросов count(*)​

Механизм обеспечения согласованности в модели Aggregate значительно снижает эффективность некоторых запросов. Наиболее характерный пример: запрос count(*):

SELECT COUNT(*) FROM table;

В других базах данных такой запрос возвращает результат очень быстро. Такие подходы, как «подсчёт строк во время загрузки с сохранением полученного количества» или «сканирование только одного столбца при выполнении запроса для определения количества строк», позволяют получить результат с очень небольшими затратами. Однако в модели Aggregate в Doris этот запрос требует значительных ресурсов.

Для приведённых выше данных итоговый результат агрегации выглядит так:

user_iddatecost
100012017/11/2051
100012017/11/215
100022017/11/2139
100032017/11/2222

Правильный результат запроса SELECT COUNT(*) FROM table; должен быть равен 4. Однако:

  • Сканирование только столбца user_id с агрегацией во время выполнения запроса даёт 3 (10001, 10002, 10003), что неверно.
  • Сканирование только столбца user_id без агрегации во время выполнения запроса даёт 5 (всего 5 строк в обоих пакетах), что неверно.

Чтобы получить правильный результат, необходимо прочитать оба столбца: user_id и date, а затем выполнить агрегацию во время запроса. Только так можно получить правильный результат 4. То есть для запроса count(*) Doris должен просканировать все столбцы AGGREGATE KEY (в данном случае user_id и date) и агрегировать их, чтобы получить семантически корректный результат. При большом числе столбцов агрегации запросу count(*) приходится сканировать значительный объём данных.

Оптимизация производительности count(*)​

Если рабочая нагрузка содержит частые запросы count(*), добавьте дополнительный столбец, значение которого всегда равно 1, а тип агрегации задан как SUM, чтобы имитировать count(*). Измените схему таблицы из предыдущего примера следующим образом:

Имя столбцаТипТип агрегацииКомментарий
user_idBIGINTИдентификатор пользователя
dateDATEДата загрузки данных
costBIGINTSUMОбщие расходы пользователя
countBIGINTSUMДля подсчёта количества строк

При загрузке данных задавайте для столбца count постоянное значение 1. Тогда:

SELECT COUNT(*) FROM table;
-- equivalent to
SELECT SUM(count) FROM table;

Второй запрос значительно эффективнее первого.

Ограничение использования: необходимо следить за тем, чтобы строки с одинаковыми значениями столбцов AGGREGATE KEY не загружались повторно. В противном случае SELECT SUM(count) FROM table; отражает только количество исходно загруженных строк и больше не эквивалентен SELECT COUNT(*) FROM table;.

Альтернатива: измените тип агрегации столбца count из примера выше на REPLACE, сохранив постоянное значение 1. В этом случае SELECT SUM(count) FROM table; и SELECT COUNT(*) FROM table; дают одинаковый результат, а ограничений на загрузку повторяющихся строк нет.

Реализация merge-on-write в модели Unique​

Реализация merge-on-write в модели Unique не имеет описанных выше ограничений модели Aggregate. Для тех же данных merge-on-write добавляет соответствующую delete bitmap к rowset каждой загрузки, чтобы отметить перезаписанные данные.

После загрузки первого пакета:

пакет 1

user_iddatecostбит удаления
100012017/11/2050FALSE
100022017/11/2139FALSE

После загрузки второго пакета повторяющиеся строки в первом пакете помечаются как удалённые:

пакет 1

user_iddatecostбит удаления
100012017/11/2050TRUE
100022017/11/2139FALSE

пакет 2

user_iddatecostбит удаления
100012017/11/201FALSE
100012017/11/215FALSE
100032017/11/2222FALSE

При выполнении запроса все строки, помеченные в delete bitmap как удалённые, отфильтровываются, и агрегация данных не требуется. Приведённые выше данные содержат 4 действительные строки, и результат запроса также содержит 4 строки. Поэтому запрос может использовать упомянутый ранее подход с минимальными затратами: «сканировать только один столбец для определения количества строк».

Данные о производительности: в тестовых средах запросы count(*) в реализации merge-on-write модели Unique выполняются более чем в 10 раз быстрее, чем в модели Aggregate.

Модель Duplicate​

Модель Duplicate не имеет описанных выше ограничений модели Aggregate. Поскольку в этой модели отсутствует семантика агрегации, запрос count(*) может просканировать любой один столбец, чтобы получить семантически корректный результат.