炼气期DBA
(Ti D Ber Ic01xw Vm)
2026 年6 月 8 日 08:51
1
文档中关于split index key中包含数学和字母的部分,写得不明不白,一笔带过,无人看得懂是怎么计算step的,可以一步一步的写个真实的详细的步骤吗?
问题1:
upper 和 lower 的值会先编码成 byte 数组
请问这里如何将upper和lower值编码成byte数组呢?我们怎么计算出这个数组的呢?
问题2:
lower 和 upper 各取前 8 字节转成 uint64
请问这里如何取值8字节并转成unit64呢?可以使用一个案例说出详细步骤吗?空有文字我们难以脑补。
问题3:
step = (upper - lower)/num
请问这个num是如何确定的呢?是指kv的数量还是regions个数?
问题4:
计算出 step 后再将 step 编码成 byte 数组
请问这个如何编码成byte数组,该如何计算,请更出详细的计算步骤
问题5:
添加到之前 upper 和 lower 的最长公共前缀后面组成一个 key 后去做切分
请列出详细步骤。
我想问下,这种低级繁琐的计算题,代码为什么不自动实现?为何需要人为的去计算?数据库人性化和智能化可以实现吗?
如果不是因为热点引起一个节点CPU爆掉,导致全业务停摆,我们也不会来看这个看不懂的文档。
均匀切分
索引均匀切分与行数据均匀切分的原理一样,只是计算 step 的值较为复杂,因为 index_value 可能不是整数。
upper 和 lower 的值会先编码成 byte 数组,去掉 lower 和 upper byte 数组的最长公共前缀后,从 lower 和 upper 各取前 8 字节转成 uint64,再计算 step = (upper - lower)/num。计算出 step 后再将 step 编码成 byte 数组,添加到之前 upper和 lower的最长公共前缀后面组成一个 key 后去做切分。示例如下:
如果索引 idx 的列也是整数类型,可以用如下 SQL 语句切分索引数据:
SPLIT TABLE t INDEX idx BETWEEN (-9223372036854775808) AND (9223372036854775807) REGIONS 16;
该语句会把表 t 中 idx 索引数据 Region 从 minInt64 到 maxInt64 之间均匀切割出 16 个 Region。
1 个赞
小龙虾爱大龙虾
(Minghao Ren)
2026 年6 月 9 日 03:17
2
这里计算 region split 切分后的边界,本来就是自动的啊
问题1:
upper 和 lower 的值会先编码成 byte 数组
请问这里如何将upper和lower值编码成byte数组呢?我们怎么计算出这个数组的呢?
不用算,它是自动的
问题2:
lower 和 upper 各取前 8 字节转成 uint64
请问这里如何取值8字节并转成unit64呢?可以使用一个案例说出详细步骤吗?空有文字我们难以脑补。
不用算,这是自动的,代码类似 binary.BigEndian.Uint64(b byte)
问题3:
step = (upper - lower)/num
请问这个num是如何确定的呢?是指kv的数量还是regions个数?
就是你语句中写的的 region_num
SPLIT TABLE table_name [INDEX index_name] BETWEEN (lower_value) AND (upper_value) REGIONS region_num
问题4:
计算出 step 后再将 step 编码成 byte 数组
请问这个如何编码成byte数组,该如何计算,请更出详细的计算步骤
不用算,这是自动的
问题5:
添加到之前 upper 和 lower 的最长公共前缀后面组成一个 key 后去做切分
请列出详细步骤。
这步是因为前边去掉了前缀, “ 去掉 lower 和 upper byte 数组的最长公共前缀后”
总结:
这段描述主要是告诉你,对于索引的 split 是怎么计算的,因为索引可能是字符串
1 ~ 100000 分成成 4 个 region 很简单,均分就行了
1 ~ 25000
25000 ~ 50000
50000 ~ 75000
75000 ~ 100000
那如果数据是 “aa” ~ “ab” 呢,或者是 “你好” ~ “中国” 呢 (PS:这里的数值都是随便写的,只为了举例),就需要用到前边说的算法把他们均分一下
炼气期DBA
(Ti D Ber Ic01xw Vm)
2026 年6 月 9 日 06:25
3
现在说的是手工split index.
你可以自己建一张表,然后创建一个索引,你再把索引split region一下看看,
SPLIT TABLE t INDEX idx
克里克里克
(Ti D Ber H052ej9m)
2026 年6 月 9 日 07:18
4
就还是按照正常的流程处理吧。上面给的应该是内部底层的划分。直接按照key值拆分就行。
mysql> select count(1) from INFORMATION_SCHEMA.tikv_region_status d where d.TABLE_NAME=‘ccc’ and d.IS_INDEX=1 and d.INDEX_NAME=‘i_12’;-- table_name
±---------+
| count(1) |
±---------+
| 3 |
±---------+
1 row in set (0.09 sec)
mysql> select min(table_name),max(table_name) from ccc;
±----------------±----------------+
| min(table_name) | max(table_name) |
±----------------±----------------+
| aaa | zzz |
±----------------±----------------+
1 row in set (0.00 sec)
mysql> split table tidbcs.ccc index i_12 between (‘aaa’) and (‘zzz’) regions 3;
±-------------------±---------------------+
| TOTAL_SPLIT_REGION | SCATTER_FINISH_RATIO |
±-------------------±---------------------+
| 3 | 1 |
±-------------------±---------------------+
1 row in set (0.61 sec)
mysql> select count(1) from INFORMATION_SCHEMA.tikv_region_status d where d.TABLE_NAME=‘ccc’ and d.IS_INDEX=1 and d.INDEX_NAME=‘i_12’;-- table_name
±---------+
| count(1) |
±---------+
| 5 |
±---------+
1 row in set (0.17 sec)
小龙虾爱大龙虾
(Minghao Ren)
2026 年6 月 9 日 07:41
5
SPLIT TABLE t INDEX idx 语句并没有让你填每个 region 的范围啊,只让你填上下界和 region 数,要测试啥?
SPLIT TABLE table_name [INDEX index_name] BETWEEN (lower_value) AND (upper_value) REGIONS region_num
炼气期DBA
(Ti D Ber Ic01xw Vm)
2026 年6 月 9 日 08:54
6
你说的上界和界就是lower_value和upper_values,lower_value和upper_value 如果计算出这两个值的呢?文档就没写清楚。
比如下图,key包含有字母和数字,如何split table呢?
start_key: t_192_5f7280000000000145e9
end_key: 78000000
炼气期DBA
(Ti D Ber Ic01xw Vm)
2026 年6 月 9 日 08:55
7
表中已经有大量数据了,只是想把其中某个regions做split,你这个是一次把整个索引的做split。
小龙虾爱大龙虾
(Minghao Ren)
2026 年6 月 11 日 08:14
8
预切分数据,是自己知道数据大概是什么范围,然后去执行 split 语句,而你这种自己想切分 region 的,有个更合适的 api
pd-ctl 支持切分 region,不用制定 key,只需要指定 region_id 就行了
operator add split-region 1 --policy=approximate // 将 Region 1 对半拆分成两个 Region,基于粗略估计值
operator add split-region 1 --policy=scan // 将 Region 1 对半拆分成两个 Region,基于精确扫描值
炼气期DBA
(Ti D Ber Ic01xw Vm)
2026 年6 月 11 日 09:22
9
感谢分享,我自己测试一下。
这分割region真的是5花8门。