更新时间:2022-08-16 GMT+08:00

UNI_HASH算法

适用场景

适用于需要按用户ID或订单ID进行分库的场景。

使用说明

拆分键的数据类型必须是整数类型(INT, INTEGER, BIGINT, MEDIUMINT, SMALLINT, TINYINT, DECIMAL, NUMERIC)或字符串类型。

路由方式

根据分库键的键值按分库/表数取余。如果键值是字符串,则字符串会被计算成哈希值再对分库/表数取余。

例如,UNI_HASH('6')等价于6 % D(D是分库数目)。

算法计算方式

方式一:拆分键是整型

表1 拆分键是整型时的计算方式

条件

计算方式

举例

分库拆分键 ≠ 分表拆分键

分库路由结果 = 分库拆分键值 % 分库数

分表路由结果 = 分表拆分键值 % 分表数

分库 :16 % 8 = 0

分表:16 % 3 = 1

分库拆分键 = 分表拆分键

分库路由结果 = 拆分键值 % 分库数

分表路由结果 = (拆分键值%分库数)*分表数+(拆分键值 /分库数)%分表数

分库 :16 % 8 = 0

分表:(16 % 8) *3 + (16/8)%3 = 2

方式二:拆分键是字符类型

表2 拆分键是字符型时的计算方式

条件

计算方式

举例

分库拆分键 ≠ 分表拆分键

分库路由结果 = hash(分库拆分键值) % 分库数

分表路由结果 = hash(分表拆分键值) % 分表数

hash(‘abc’)=‘abc’.hashCode()=96354

分库 :96354 % 8 = 2;

分表 :96354 % 3 = 0;

分库拆分键 = 分表拆分键

分库路由结果 = hash(拆分键值) % 分库数

分表路由结果 = (hash(拆分键值) %分库数)*分表数+( hash(拆分键值) /分库数)%分表数

分库 :96354% 8 = 2

分表 :( 96354 % 8) *3 + (96354/8)%3 = 8

建表语法

create table uni_hash_tb( 
    id int, 
    name varchar(30) DEFAULT NULL, 
    create_time datetime DEFAULT NULL, 
    primary key(id) 
)ENGINE=InnoDB DEFAULT CHARSET=utf8 
dbpartition by UNI_HASH(ID) 
tbpartition by UNI_HASH(name) tbpartitions 3;

注意事项

  • 拆分键和键值皆不能修改。
  • UNI_HASH算法是简单取模,要求拆分列的值自身分布均衡才能保证哈希均衡。

与MOD_HASH的比较

  • 在使用 UNI_HASH 分库但不分表时,UNI_HASH 和 MOD_HASH 的路由方式一样,都是根据分库键的键值按分库数取余。
  • 分库和分表都使用同一个拆分键进行 MOD_HASH 时,随着分表数的变化,同一个键值分到的分库不是固定的。
  • 分库和分表都使用同一个拆分键进行 UNI_HASH 时,无论分表数是多少,同一个键值总是分到相同的分库。
  • 如果两张逻辑表需要根据同一个拆分键进行分库分表,但分表数不同,那么当两张表按该拆分键进行 JOIN 时,如果使用 MOD_HASH 会出现跨库 JOIN,而 UNI_HASH 不会有跨库 JOIN。