主键表
主键表使用了StarRocks设计的新存储引擎。其主要优势在于支持实时数据更新,同时确保复杂即席查询的高效性能。在实时业务分析中,决策可以从主键表中受益,因为它使用最新的数据进行实时分析,从而减轻数据分析中的数据延迟。 然而,主键并不是免费的午餐。如果使用不当,可能导致不必要的资源浪费。
因此,在本节中,我们将指导您如何更有效地使用主键模型以达到预期效果。
选择主键索引
主索引是主键表中最关键的组件。主键索引用于存储主键值与由主键值标识的数据行位置之间的映射。
目前,我们支持三种类型的主键索引:
- 全内存主键索引。
PROPERTIES (
"enable_persistent_index" = "false"
);
- 基于本地磁盘的持久化主键索引。
PROPERTIES (
"enable_persistent_index" = "true",
"persistent_index_type" = "LOCAL"
);
- 云原生持久化主键索引。
PROPERTIES (
"enable_persistent_index" = "true",
"persistent_index_type" = "CLOUD_NATIVE"
);
我们不推荐使用内存索引,因为它可能导致显著的内存资源浪费。
如果您使用的是存算分离(弹性)StarRocks集群,我们建议选择云原 生持久化主键索引。与基于本地磁盘的持久化主键索引不同,它将完整的索引数据存储在远程对象存储中,本地磁盘仅作为缓存。与基于本地磁盘的持久化主键索引相比,其优势包括:
- 不依赖于本地磁盘容量。
- 数据分片重新平衡后无需重建索引。
选择主键
主键通常不帮助加速查询。您可以使用 ORDER BY 子句指定与主键不同的列作为排序键以加速查询。因此,在选择主键时,您只需考虑在数据导入和更新过程中的唯一性。
主键越大,消耗的内存、I/O和其他资源就越多。因此,通常建议避免选择过多或过大的列作为主键。主键的默认最大大小为128字节,由 be.conf 中的 primary_key_limit_size 参数控制。
您可以增加 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);
内存使用
主键表使用的内存可以通过 mem_tracker 监控:
//查看整体内存统计
http://be_ip:be_http_port/mem_tracker
// 查看主键表内存统计
http://be_ip:be_http_port/mem_tracker?type=update
// 查看主键表内存统计的更多细节
http://be_ip:be_http_port/mem_tracker?type=update&upper_level=4
mem_tracker 中的 update 项记录了主键表使用的全部内存,例如主键索引、Delete Vector 等。
您还可以通过指标监控服务监控此 update 项。例如,在 Grafana 中,您可以通过(红框中的项目)查看更新项:

更多关于使用 Prometheus 和 Grafana 的监控和告警信息: https://docs.starrocks.io/docs/administration/management/monitoring/Monitor_and_Alert/
如果您对内存使用敏感,并希望在主键表的导入过程中减少内存消耗,可以通过以下配置实现:
be.conf
l0_max_mem_usage = (一些小于 104857600 的值,默认是 104857600)
skip_pk_preload = true
// 存算一体集群
transaction_apply_worker_count = (一些小于 CPU 核心数的值,默认是 CPU 核心数)
// 存算分离集群
transaction_publish_version_worker_count = (一些小于 CPU 核心数的值,默认是 CPU 核心数)
l0_max_mem_usage 控制每个 tablet 的持久化主键索引的最大内存使用量。transaction_apply_worker_count 和 transaction_publish_version_worker_count 都控制用于处理主键表中的 upsert 和 delete 的最大线程数。
但需要记住,减少 l0_max_mem_usage 可能会增加 I/O 压力,而减少 transaction_apply_worker_count 或 transaction_publish_version_worker_count 可能会减慢数据摄取速度。