聚簇索引 (clustered index) 是 TiDB 从 v5.0 开始支持的特性,用于控制含有主键的表数据的存储方式。通过使用聚簇索引,TiDB 可以更好地组织数据表,从而提高某些查询的性能。有些数据库管理系统也将聚簇索引称为“索引组织表” (index-organized tables)。
目前 TiDB 中含有主键的表分为以下两类:
NONCLUSTERED,表示该表的主键为非聚簇索引。在非聚簇索引表中,行数据的键由 TiDB 内部隐式分配的 _tidb_rowid 构成,而主键本质上是唯一索引,因此非聚簇索引表存储一行至少需要两个键值对,分别为
_tidb_rowid(键)- 行数据(值)
主键列数据(键) - _tidb_rowid(值)
CLUSTERED,表示该表的主键为聚簇索引。在聚簇索引表中,行数据的键由用户给定的主键列数据构成,因此聚簇索引表存储一行至少只要一个键值对,即
主键列数据(键) - 行数据(值)
TiDB v6.5 之前,默认情况下,非整数主键、没有主键的表或者建表时显式指定 nonclustered 非聚簇的表,TiDB 会使用一个隐式的自增 rowid。大量执行 INSERT 插入语句时,由于 rowid 自增分配,会把数据集中写入单个 Region,造成写入热点。通过设置 SHARD_ROW_ID_BITS,可以把 rowid 打散写入多个不同的 Region,缓解写入热点问题。
但是,SHARD_ROW_ID_BITS 配置同时会带来写入数据不聚集的问题,从下图中可以看出,同一时间写入的数据,由于 SHARD_ROW_ID_BITS = 2,分布在四个不同的 Region 上。如果语句条件是根据时间进行范围扫,TableRowidScan 算子的 cop task 会增加 3 倍。
如果建表时指定 shard_row_id_bits 时,希望建表时就均匀切分 Region,可以考虑配合 PRE_SPLIT_REGIONS 一起使用,用来在建表成功后就开始预均匀切分 2^(PRE_SPLIT_REGIONS) 个 Region。但由于新建表或分区的分裂操作实际产生的是空 Region,如果分裂打散操作距离写入存在一定时间间隔,则 Region 可能会被合并,从而导致无法真正规避写入热点问题。此时可以为表或分区添加 merge_option 属性,设置为 deny 来解决问题。
禁止属于某个表的 Region 被合并
ALTER TABLE t ATTRIBUTES 'merge_option=deny';
网友评论