因为聚簇主键的原因,在mysql和mariadb中,用UUID做主键和用数值型ID做主键,性能上还是有比较大差别。在mysql或mariadb中,可以给表添加自增主键,自增主键是在数据insert表后才能获取到,很多情况下,有可能是要先获取这个自增ID(尤其是业务关联操作,父子表的关联新增等),这样就需要类似oracle中的序列sequence的功能。
以下是我的一个思路:
一、创建一个ID表:
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tb_sys_id
-- ----------------------------
DROP TABLE IF EXISTS `tb_sys_id`;
CREATE TABLE `tb_sys_id` (
`NEW_ID` bigint(20) NOT NULL COMMENT '最大ID',
PRIMARY KEY (`NEW_ID`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
创建表后,先在这个表中新增ID为1的一行数据。
二、创建一个自定义函数:
CREATE DEFINER=`root`@`%` FUNCTION `get_next_id`(`v_id_count` int) RETURNS varchar(1000) CHARSET utf8
BEGIN
declare v_id_list varchar(1000);
declare v_next_id int default 1;
declare v_index int default 1;
while v_index <= v_id_count do
update tb_sys_id set new_id=new_id+1;
select new_id into v_next_id from tb_sys_id limit 1;
if v_id_list='' then
set v_id_list=v_next_id;
else
select concat_ws(',',v_id_list,v_next_id) into v_id_list;
end if;
set v_index = v_index + 1;
end while;
return v_id_list;
END
因为ID表创建好后,已经新增了一条ID为1的数据,因此上面的函数中就只做update,省去做新增与更新的判断处理。通过这个函数可以一次获取一个或多个ID,返回是一个以逗号分割的ID字符串(一次返回的ID不要太多),比如:select get_next_id(5)
当然一个ID表,在业务复杂的系统中会存在竞争瓶颈,我们可以创建多个ID表,每个ID表针对不同的业务表,甚至是针对某个特定业务表创建一个ID表,mysql和mariadb还可以创建内存表(定时将内存表数据持久化到硬盘中),速度上我没有做过多测试。
延伸开,针对数据分表的合并采用自增ID主键冲突的问题,我们也可以用此思路,我们可以创建不同初始ID值表,比如不同的分表,比如分表1是从1~1000万,分表2的ID从1000万~2000万,以此规则。
这些仅仅是我的一个思路,如果大家有更好的思路,欢迎大家给我留言。