Blog

Лучшие практики#2

ЧАСТЬ 2: Моделирование данных

Стандарты создания таблиц

  • Поддерживается только кодировка UTF8.
  • Переименование столбцов не поддерживается (скоро будет добавлено).
  • Максимальная длина VARCHAR: 1048576.
  • Для KEY-столбцов нельзя использовать типы FLOAT и DOUBLE.
  • Имена каталогов данных, баз данных, таблиц, представлений, пользователей и ролей чувствительны к регистру; имена столбцов и разделов - нет.
  • В таблицах с первичным ключом общий размер столбцов первичного ключа не должен превышать 128 байт.

Какой тип таблицы выбрать?

  • Используйте таблицу с дублированными ключами для хранения детальных записей (факт-таблицы).
  • Используйте таблицу с первичным ключом для таблиц, имеющих уникальный ненулевой столбец, с частыми операциями записи и чтения, где неключевые столбцы используют индексы.
  • Используйте таблицу с уникальным ключом для таблиц с уникальным столбцом, который может быть NULL, с частыми операциями записи и редкими чтениями.
  • Используйте агрегатную таблицу для хранения только агрегированных данных.
  • Подробное сравнение типов таблиц см. в документации.

Выбор столбцов сортировки и префиксных индексов

  • Для версий StarRocks до 3.0 столбцы сортировки в таблицах с первичным ключом указываются через PRIMARY KEY. В StarRocks 3.0 и новее столбцы сортировки в моделях с первичным ключом задаются через ORDER BY.
  • Префиксный индекс - это разреженный индекс, введенный поверх столбцов сортировки для дальнейшего повышения эффективности запросов. Все префиксные индексы загружаются в память для оптимальной производительности. При использовании префиксных индексов учитывайте:
  • Столбцы, часто используемые в условиях запросов, должны быть столбцами сортировки. Например, разместите user_id первым, если запросы часто фильтруют по user_id.
  • Идеальное количество столбцов сортировки - 3-5. Слишком много столбцов увеличивают накладные расходы на сортировку и замедляют загрузку данных.
  • Префиксные индексы не должны превышать 36 байт и включать более 3 столбцов. VARCHAR-столбцы будут усекаться в префиксных индексах, а типы FLOAT или DOUBLE не допускаются.
Поэтому, сочетая с реальными бизнес-сценариями запросов, при определении ключевых столбцов и порядка полей следует полностью учитывать преимущества префиксных индексов. Размещайте часто запрашиваемые ключевые столбцы в начале и по возможности выбирайте для этих полей типы данных, такие как дата или целочисленные типы (например, int).
Пример:
CREATE TABLE site_access (
site_id BIGINT DEFAULT '10',
city_code INT,
site_name VARCHAR(50),
pv BIGINT DEFAULT '0'
)
DUPLICATE KEY(site_id, city_code, site_name)
DISTRIBUTED BY HASH(site_id);
В таблице 'site_access' префиксный индекс состоит из site_id (8 байт) + city_code (4 байта) + site_name (первые 24 байта).
select sum(pv) from site_access where site_id = 123 and city_code = 2;
Если условие запроса включает только столбцы site_id и city_code, как показано ниже, это может значительно сократить количество сканируемых строк данных:
select sum(pv) from site_access where site_id = 123 and city_code = 2;
Если условие запроса включает только столбец site_id, как показано ниже, можно точно определить строки, содержащие только site_id:
select sum(pv) from site_access where site_id = 123;
Если условие запроса включает только столбец city_code, как показано ниже, необходимо сканировать все строки данных, и эффект сортировки значительно снижается:
select sum(pv) from site_access where city_code = 2;
Если соотношение комбинированных запросов по site_id и city_code к запросам только по city_code примерно одинаково, рассмотрите возможность создания синхронизированного материализованного представления для изменения порядка столбцов и повышения производительности запросов. В этом случае мы размещаем столбец city_code первым в материализованном представлении.
create materialized view site_access_city_code_mv asselect
city_code,
site_id,
site_name,
pv
from
site_access;
Неудачный пример:
CREATE TABLE site_access_bad
(
site_name VARCHAR(20),
site_id BIGINT DEFAULT '10',
city_code INT,
pv BIGINT DEFAULT '0'
)
PRIMARY KEY(site_id)
DISTRIBUTED BY HASH(site_id)
ORDER BY(site_id,city_code);
В таблице 'site_access_bad' префиксный индекс включает только site_name.

Выбор партиционирования

Рекомендации:
  • Используйте неизменяемый временной столбец для фильтрации WHERE при создании партиций.
  • Выбирайте динамические партиции для сценариев с необходимостью удаления устаревших данных.
  • Создавайте партиции для данных с выраженным разделением на "горячие" и "холодные" данные (например, часто обновляемые данные за последнюю неделю можно партиционировать ежедневно).
Требования:
  • Каждая партиция не должна превышать 100 ГБ.
  • Таблицы объемом более 50 ГБ или 5 миллионов строк должны иметь партиции.
  • Создавайте партиции по необходимости; избегайте создания большого количества пустых партиций, чтобы предотвратить чрезмерное использование памяти FE метаданными.
Поддерживаемые типы партиционирования:
  • Время (Range, Expression партиции)
  • Строки (List партиции)
  • Числа (Range, List партиции)
По умолчанию поддерживается до 1024 партиций (настраивается, но обычно не требуется).

Выбор бакетирования

Требования:
  • В production-среде необходимо использовать 3 реплики.
Определение количества бакетов:
  • Ориентировочно: 1 бакет на 1 ГБ данных (исходные данные оцениваются с коэффициентом сжатия 7:1–10:1).
  • Если расчетное количество бакетов меньше числа узлов BE, итоговое количество бакетов должно соответствовать числу узлов BE (например, 6 узлов BE → 6 бакетов).
  • Для непартиционированных таблиц не используйте динамическое бакетирование — оценивайте количество бакетов на основе фактического объема данных.
  • Избегайте динамического бакетирования, если партиции сильно различаются по объему данных.
Как избежать перекоса данных:
  • Используйте столбцы с низкой кардинальностью (например, user_id, transaction_id) для бакетирования, если они часто фигурируют в условиях WHERE.
  • Если запросы часто включают city_id и site_id вместе, а city_id имеет низкую кардинальность, используйте оба столбца для бакетирования (но это снизит эффективность при запросах только по city_id).
  • Если нет подходящих столбцов, рассмотрите случайное бакетирование (но это исключит преимущества "бакетного сокращения").
  • Для соединения таблиц с >1000 строк каждая используйте Colocate join.

Типы полей

Рекомендации:
  • Избегайте значений NULL.
  • Используйте правильные типы данных для временных и числовых столбцов (например, не храните дату в VARCHAR).

Выбор индексов

Bitmap-индекс:
  • Подходит для столбцов с кардинальностью 10 000–100 000.
  • Эффективен для запросов с условиями = или [NOT] IN.
  • Не поддерживается для FLOAT, DOUBLE, BOOLEAN, DECIMAL.
Bloom Filter-индекс:
  • Подходит для столбцов с кардинальностью >100 000 и низкой повторяемостью.
  • Эффективен для запросов с IN и =.
  • Не поддерживается для TINYINT, FLOAT, DOUBLE, DECIMAL.
Примечание:
  • В детальных и первично-ключевых моделях Bitmap-индексы можно создавать для всех столбцов.
  • В агрегатных и обновляемых моделях Bitmap-индексы поддерживаются только для ключевых столбцов.