Таблицы Primary Key¶
Таблица Primary Key использует новый движок хранения, разработанный в StarRocks. Её основное преимущество — поддержка обновления данных в реальном времени при сохранении эффективной производительности для сложных ad‑hoc запросов. В real‑time бизнес‑аналитике принятие решений выигрывает от таблиц Primary Key: они используют самые свежие данные для немедленного анализа, снижая задержку данных в аналитике.
Однако Primary Key — не «волшебная палочка». При неправильном использовании это может приводить к лишним затратам ресурсов.
Поэтому в этом разделе мы подскажем, как эффективнее использовать модель Primary Key, чтобы получать ожидаемые результаты.
Выбор индекса Primary Key¶
Primary index — критически важный компонент таблицы Primary Key. Индекс по первичному ключу хранит отображение между значениями ключа и расположением строк данных, идентифицируемых этим ключом.
В настоящее время поддерживаются три типа индекса по первичному ключу:
Полностью in‑memory индекс по первичному ключу.
PROPERTIES ( "enable_persistent_index" = "false" );Персистентный индекс по первичному ключу на локальном диске.
PROPERTIES ( "enable_persistent_index" = "true", "persistent_index_type" = "LOCAL" );Облачный (cloud‑native) персистентный индекс по первичному ключу.
PROPERTIES ( "enable_persistent_index" = "true", "persistent_index_type" = "CLOUD_NATIVE" );
Мы НЕ рекомендуем использовать in‑memory индексацию, так как это может приводить к значительным потерям памяти.
Если вы используете кластер StarRocks в режиме shared‑data (elastic), рекомендуем выбрать cloud‑native персистентный индекс по первичному ключу. В отличие от персистентного индекса на локальном диске он хранит полный индекс в удалённом object storage, а локальные диски используются только как кэш. По сравнению с локальным вариантом преимущества включают:
Отсутствие зависимости от ёмкости локального диска.
Отсутствие необходимости перестраивать индексы после ребалансировки шардов данных.
Выбор Primary Key¶
Как правило, первичный ключ сам по себе не ускоряет запросы. Вы можете указать столбец, отличный от первичного ключа, в качестве sort key, используя ORDER BY, чтобы ускорить запросы. Поэтому при выборе первичного ключа учитывайте в первую очередь уникальность в процессах импорта и обновления данных.
Чем больше (шире) первичный ключ, тем больше потребление памяти, I/O и других ресурсов. Обычно рекомендуется избегать слишком большого числа столбцов в ключе и чрезмерно «широких» столбцов. Максимальный размер первичного ключа по умолчанию — 128 байт; он управляется параметром primary_key_limit_size в be.conf.
Вы можете увеличить primary_key_limit_size, чтобы выбрать более крупный ключ, но учитывайте рост потребления ресурсов.
Сколько места в хранилище и памяти занимает персистентный индекс?
Формула стоимости по месту в хранилище¶
(key size + 8 bytes) * row count * 50%
50% — оценка эффективности сжатия; фактический эффект зависит от самих данных.
Формула стоимости по памяти¶
min(l0_max_mem_usage * tablet cnt, update_memory_limit_percent * BE process memory);
Использование памяти¶
Память, используемую таблицей Primary Key, можно мониторить через mem_tracker:
//View the overall memory statistics
http://be_ip:be_http_port/mem_tracker
// View primary key table memory statistics
http://be_ip:be_http_port/mem_tracker?type=update
// View primary key table memory statistics with more details
http://be_ip:be_http_port/mem_tracker?type=update&upper_level=4
Элемент update в mem_tracker учитывает всю память, используемую таблицей Primary Key, включая primary key index, delete vector и т. д. Также можно мониторить этот элемент update через систему метрик. Например, в Grafana вы можете посмотреть этот элемент (показан в красной рамке):

Подробнее о мониторинге и алертах с Prometheus и Grafana: https://docs.starrocks.io/docs/administration/management/monitoring/Monitor_and_Alert/
Если вы чувствительны к использованию памяти и хотите снизить её потребление во время импорта в PK‑таблицу, используйте следующую конфигурацию:
be.conf
l0_max_mem_usage = (some value which smaller than 104857600, default is 104857600)
skip_pk_preload = true
// Shared-nothing cluster
transaction_apply_worker_count = (some value smaller than cpu core number, default is cpu core number)
// Shared-data cluster
transaction_publish_version_worker_count = (some value smaller than cpu core number, default is cpu core number)
l0_max_mem_usage управляет максимальным использованием памяти персистентного индекса Primary Key на один tablet. Параметры transaction_apply_worker_count и transaction_publish_version_worker_count управляют максимальным числом потоков, используемых для обработки upsert и delete в таблицах Primary Key.
Помните: снижение l0_max_mem_usage может увеличить нагрузку на I/O, а уменьшение transaction_apply_worker_count или transaction_publish_version_worker_count может замедлить загрузку данных.
Баланс между ресурсами компакции, «свежестью» данных и латентностью запросов¶
По сравнению с другими моделями таблиц, таблицы Primary Key требуют дополнительных операций поиска по индексу и формирования delete vector при импорте, обновлениях и удалениях, что вносит дополнительный оверхед по ресурсам. Поэтому необходимо балансировать между тремя факторами:
Ограничения по ресурсам компакции
Свежесть данных
Латентность запросов
Свежесть данных и латентность запросов¶
Если вам нужна высокая свежесть данных одновременно с низкой латентностью запросов, это означает высокочастотные записи, которые вы хотите быстро компактизировать. Тогда потребуется больше ресурсов компакции для обработки этих записей:
// shared-data
be.conf
compact_threads = 4
// shared-nothing
be.conf
update_compaction_num_threads_per_disk = 1
update_compaction_per_tablet_min_interval_seconds = 120
Можно увеличить compact_threads и update_compaction_num_threads_per_disk или уменьшить update_compaction_per_tablet_min_interval_seconds, чтобы добавить ресурсы компакции для высокой частоты записей.
Как понять, справляется ли текущая конфигурация компакции с нагрузкой на запись? Наблюдайте так:
Для shared‑data кластера: если компакция не успевает за скоростью ingest, возможны замедления или даже ошибки записи и остановка ingest.
a. Замедление ingest. Используйте
show proc /transactions/{db_name}/running';, чтобы проверить текущие транзакции, и если в ErrMsg есть сообщения вроде:Partition's compaction score is larger than 100.0, delay commit for xxxms. You can try to increase compaction concurrencyэто означает замедление ingest.
Пример:
mysql> show proc '/transactions/test_pri_load_c/running'; +---------------+----------------------------------------------+------------------+-------------------+--------------------+---------------------+------------+-------------+------------+----------------------------------------------------------------------------------------------------------------------------+--------------------+------------+-----------+--------+ | TransactionId | Label | Coordinator | TransactionStatus | LoadJobSourceType | PrepareTime | CommitTime | PublishTime | FinishTime | Reason | ErrorReplicasCount | ListenerId | TimeoutMs | ErrMsg | +---------------+----------------------------------------------+------------------+-------------------+--------------------+---------------------+------------+-------------+------------+----------------------------------------------------------------------------------------------------------------------------+--------------------+------------+-----------+--------+ | 1034 | stream_load_d2753fbaa0b343acadd5f13de92d44c1 | FE: 172.26.94.39 | PREPARE | FRONTEND_STREAMING | 2024-10-24 13:05:01 | NULL | NULL | NULL | Partition's compaction score is larger than 100.0, delay commit for 6513ms. You can try to increase compaction concurrency, | 0 | 11054 | 86400000 | | +---------------+----------------------------------------------+------------------+-------------------+--------------------+---------------------+------------+-------------+------------+----------------------------------------------------------------------------------------------------------------------------+--------------------+------------+-----------+--------+b. Остановка ingest. Если возникает ошибка вида:
Failed to load data into partition xxx, because of too large compaction score, current/limit: xxx/xxx. You can reduce the loading job concurrency, or increase compaction concurrencyэто указывает на остановку ingest из‑за того, что компакция не поспевает за высокой частотой записей.
Для shared‑nothing кластера стратегии замедления ingest нет: если компакция не успевает, ingest завершится ошибкой:
Failed to load data into tablet xxx, because of too many versions, current/limit: xxx/xxx. You can reduce the loading job concurrency, or increase loading data batch size. If you are loading data with Routine Load, you can increase FE configs routine_load_task_consume_second and max_routine_load_batch_size.
Свежесть данных и ограничения по ресурсам компакции¶
Если ресурсы компакции ограничены, но требуется поддерживать приемлемую свежесть данных, придётся пожертвовать частью латентности запросов.
Можно изменить конфигурацию так:
Shared‑data кластер
fe.conf
lake_ingest_slowdown_threshold = xxx (default is 100, you can increase it)
lake_compaction_score_upper_bound = xxx (default is 2000, you can increase it)
Параметр lake_ingest_slowdown_threshold управляет порогом замедления ingest. Если compaction score партиции превышает этот порог, система начнёт замедлять загрузку. Аналогично, lake_compaction_score_upper_bound задаёт порог остановки ingest.
Shared‑nothing кластер
be.conf
tablet_max_versions = xxx (default is 1000, you can increase it)
tablet_max_versions определяет порог срабатывания остановки ingest.
Увеличение этих параметров позволяет системе принимать больше мелких файлов данных и реже запускать компакции, но это ухудшит латентность запросов.
Латентность запросов и ограничения по ресурсам компакции¶
Если вам нужна хорошая латентность запросов при ограниченных ресурсах компакции, уменьшайте частоту записей и формируйте более крупные батчи загрузки.
Конкретные приёмы зависят от метода загрузки; см. соответствующие разделы по методам, где описано, как снизить частоту и увеличить размер батчей.