ЧАСТЬ 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-индексы поддерживаются только для ключевых столбцов.