首先,如果你既想主键连续自增,又想避免写热点问题,不需要你的解决方案3,你直接建表时指定使用主键自增(自增缓存设置为1)且是非聚簇索引,同时shard分片,然后预先切片就能达到你要的效果。
建表语句如下:
CREATE TABLE t_autoincre_noclus_sd (a BIGINT PRIMARY KEY NONCLUSTERED AUTO_INCREMENT, b VARCHAR(255)) SHARD_ROW_ID_BITS = 4 pre_split_regions=4 AUTO_ID_CACHE 1;
可以用下面sql测试
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('1');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('2');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('3');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('4');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('5');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('6');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('7');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('8');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('9');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('10');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('11');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('12');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('13');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('14');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('15');
INSERT INTO t_autoincre_noclus_sd(b) VALUES ('16');
SELECT _tidb_rowid,t.* FROM t_autoincre_noclus_sd t ORDER BY a;
SELECT * FROM INFORMATION_SCHEMA.`TIKV_REGION_STATUS` b WHERE b.`TABLE_NAME`='t_autoincre_noclus_sd';
你会发现你插入的数据,既符合主键是连续自增,同时也不存在写热点。同时你所担心的提前切分的Region用完其实不存在的,因为预分的region用完了,你SHARD_ROW_ID_BITS还是会保证你后面每插入数据都是分散到不同的region上的。
这个方案其实唯一的缺点就是,非聚簇索引表相对于聚簇索引表的效率其实是稍微有点差的,毕竟没有点查了。
至于你下面这个分区的问题,你只要理解tidb的分区实际上是物理分区,它每个分区相当于1个物理小表,所以你同一年插入很多数据,相当于都插入到了你对应分区的那个小物理表中,该有热点还是有热点的。区别只是和上面一样,你是否已经预先打散到不同的region中。
另外在前面的版本中,主键是必须包含分区键的。