
# 如何设计表主键
在使用HBase进行大数据存储时，数据的高效访问依赖于合理的数据分区策略。然而，由于HBase使用字典序进行数据分区排序，如果主键设计不当，可能会导致数据热点问题，即大量数据集中在少数几个节点上，影响系统性能。通过设计主键前缀尽可能打散，可以有效避免数据热点，提高数据访问效率。
#### 实例场景
若您原先使用关系型数据库时，采用自增Int类型作为主键，且将该主键配置直接沿用至GeminiDB HBase，当数据量增长到一定规模后，极易出现分区数据分布不均的问题，具体场景如下：
假设您的主键随数据量累积已覆盖0-1999999的Int值，而创建GeminiDB HBase预分区时，仅设置了\[0, 1, 2, 3, 4, 5, 6, 7, 8, 9\]的分区键 ------ 此时，对应字典序范围\[1, 2)的分区（即分区 "2"），会承载远超其他分区的数据量。原因在于，所有主键为1000000-1999999的数据（主键前缀均为 "1"），都会按照字典序规则落入该分区，导致该分区成为 "热点分区"。
尽管GeminiDB HBase支持"单分区数据量达到阈值后自动分裂"，但分区分裂过程存在一定时延，无法实时适配高吞吐场景的性能需求。因此，建议在使用前提前通过合理设计打散数据并[进行合理预分区](https://support.huaweicloud.com/hbaseug-nosql/nosql_hbase_133.html#nosql_hbase_133)（而非直接沿用关系型数据库的自增 Int 主键），从而避免热点分区问题，为高吞吐业务场景提供更稳定的性能支撑。
#### 解决方案
因为你的 ID 是一个不断递增的长整型，如果直接把它作为 HBase 的行键写入，所有的新数据都会集中到同一台 RegionServer 上，造成严重的热点问题。因此需要在行键前面增加一个"分桶"或"盐值"前缀，把写入流量均匀分布到多个 Region 上。。
做法是这样的：在真正的 ID 之前，先加一个分桶前缀。分桶前缀可以通过对 ID 取模得到，例如把 ID 除以 10 取余数，得到 0 到 9 之间的数字，这个数字就是分桶前缀。每条数据在写入时都带上自己的分桶前缀，这样相同的 ID 会落到不同的 Region 上，实现均匀分布。HBase 表在创建时提前根据分桶前缀划分出对应的分区（预分区），例如分成10个或100个 Region，使每个 Region 都对应一个分桶前缀。
您可以将主键设计为 \[BucketPrefix\]\|\[Reversed ID or ID\] 的形式， BucketPrefix 规定为对除以10取余的值。 如主键 1420008 % 10 = 8， 则新主键为 **8\|1420008** ， 这样该主键将落在分区'8'上，而不是落在分区'1'中。 后续对于主键1420008的查询，也需要传入对应增加了前缀的主键 **8\|1420008** 进行单点查询。
若将不断递增的长整型ID直接作为HBase行键写入，所有新数据会集中到同一台RegionServer，引发严重的热点问题（写入压力集中，性能瓶颈显著）。为解决此问题，需在行键前增加 "分桶前缀" 或 "盐值前缀"，通过打散数据将写入流量均匀分配到多个Region，核心实现方案如下：
1. 分桶前缀的生成逻辑 分桶前缀通过对原始ID进行"取模运算"生成，确保前缀取值范围可控且分布均匀。以"按10分桶"为例：对原始ID除以10取余数，得到0-9之间的整数（如 ID=1420008 时，1420008%10=8），该整数即为分桶前缀。每条数据写入时，均需在原始ID前拼接此前缀，形成"前缀+ID"的组合行键（如 1420008 的新行键为8\|1420008）。
   
2. 配合预分区实现流量均匀 需在 HBase 表创建阶段，根据分桶前缀提前规划预分区：
   - 若按10分桶（前缀 0-9），则提前创建10个Region，每个Region对应一个分桶前缀（如Region1对应前缀0、Region2对应前缀1......Region10对应前缀9）；
   
   - 若数据量更大，可扩展为100分桶（前缀0-99），同步创建100个Region。 如此，带不同前缀的行键会精准落入对应Region（如8\|1420008会落入"前缀 8"的Region），避免原始递增ID集中到单一Region的问题，实现写入流量的全局均匀。
     
    
3. 行键格式与查询适配
   - **推荐行键格式**
     采用
     ```
     [BucketPrefix]|[ID]
     ```
     或
     ```
     [BucketPrefix]|[Reversed ID]
     ```
     的格式（"\|"为分隔符，便于区分前缀与原始ID）：
     - 若需优化ID范围查询，可将原始ID反转（如ID=1420008反转后为8000241），形成8\|8000241，避免同前缀下ID递增导致的局部热点。
     
     - 若仅需单点查询，直接使用\[BucketPrefix\]\|\[原始ID\]即可（如8\|1420008）。
       
   
   - **查询适配规则**
     后续查询原始ID（如1420008）时，需先通过相同的取模逻辑计算出分桶前缀（8），再用完整的组合行键（8\|1420008）发起单点查询，确保能精准定位到对应 Region 的数据，避免全表扫描。
     
    
通过 "分桶前缀 + 预分区" 的组合方案，可彻底解决递增 ID 带来的 HBase 热点问题，同时兼顾写入均匀性与查询效率，尤其适配高吞吐、大数据量的业务场景。
![](https://support.huaweicloud.com/hbaseug-nosql/public_sys-resources/note_3.0-zh-cn.png)
如果您需要更多的预分区来打散数据，可以将预分区键设置为\[000,002,.....,999\] 则您会有1000个预分区，将主键按如上方式 除以1000取余，并添加在主键前方即可。
