HASH算法
适用场景
适用于需要将数据均匀分布的场景或需要按时间(年、月、日、周及其组合)对数据进行拆分的场景,在SQL查询条件中,使用“=”、“IN”之类运算符相对较多。
使用说明
拆分键为表字段或表字段+日期函数。若拆分键为表字段+日期函数,其中的数据表字段必须是日期类型(DATE / DATETIME / TIMESTAMP),日期函数适用于需要按时间(年、月、日、周及其组合)对数据进行拆分的场景。
路由方式
首先102400对分库数/分表数进行分范围。
假如逻辑库分8个分片,那么102400/8=12800,则每一个分片对应的范围是:0=0-12799,1=12800-25599,2=25600-38399,3=38400-51199,4=51200-63999,5=64000-76799,6=76800-89599,7=89600-102399。
当计算路由结果时,计算拆分键值的CRC32值然后对102400取余,根据计算结果落到那个范围进行路由。
算法计算方式
方式一:拆分键非日期类型
条件 |
计算方式 |
举例 |
---|---|---|
拆分键非日期类型 |
分库路由结果 = crc32(分库拆分键值) % 102400 分表路由结果 = crc32(分表拆分键值) % 102400 |
分库/分表:crc32(16) % 102400 = 49364; 49364属于3=38400-51199,则路由到分片3 |
方式二:拆分键是日期类型
日期函数 |
计算方式 |
举例 |
---|---|---|
year() |
year(yyyy-MM-dd)=yyyy |
year(‘2019-10-11’)=2019 |
month() |
month(yyyy-MM-dd)=MM |
month(‘2019-10-11’)=10 |
weekofyear() |
weekofyear(yyyy-MM-dd)=该日期是今年的第几周 |
weekofyear (‘2019-10-11’)=41 |
day() |
day(yyyy-MM-dd)=该日期是月份的第几天 |
day (‘2019-10-11’)=11 |
条件 |
计算方式 |
举例 |
---|---|---|
拆分键是日期类型 |
分库路由结果 = crc32(日期函数(分库拆分键值)) % 102400 分表路由结果 = crc32(日期函数(分库拆分键值)) % 102400 |
分库/分表:crc32(year(‘2019-10-11’)) % 102400 = 5404; 5404属于0=0-12799,则路由到分片0 |
建表语法
假设用户需要对ID列按HASH函数进行分库不分表:
create table hash_tb ( id int, name varchar(30) DEFAULT NULL, create_time datetime DEFAULT NULL, primary key(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash (ID);
假设用户需要对ID列按HASH函数既分库又分表:
create table mod_hash_tb ( id int, name varchar(30) DEFAULT NULL, create_time datetime DEFAULT NULL, primary key(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 dbpartition by hash (ID) tbpartition by hash (ID) tbpartitions 4;
注意事项
拆分键和键值皆不能修改。