
# YYYYWEEK按年周哈希
#### 适用场景
适用于需要按年份与一年的周数进行分库的场景，建议该函数与tbpartition YYYYWEEK(ShardKey) 联合使用。
#### 使用说明
拆分键的数据类型必须是DATE / DATETIME / TIMESTAMP其中之一。
#### 路由方式
根据拆分键的时间值的年份与一年的周数计算哈希值，然后再按分库/表数取余。
例如，YYYYWEEK('2012-12-31 12:12:12') 等价于 (2013 \* 54 + 1) % D（D是分库数目/分表数）。
![](https://support.huaweicloud.com/usermanual-ddm/public_sys-resources/note_3.0-zh-cn.png)
- 此处"2012-12-31"是2013年第一周，所以为"2013\* 54+ 1"。
- YYYYWEEK的具体用法请参见[YEARWEEK函数](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_yearweek)。
 
#### 算法计算方式
表1算法计算方式 
| **条件**             | 算法                                                                                                                                                                                                                               | **举例**                                                                                                                                |
|:---|:---|:---|
| 分库拆分键 ≠ 分表拆分键      | 拆分键：yyyy-MM-dd 分库路由结果 = (yyyy \* 54 + 一年第几周) % 分库数 分表路由结果 = (yyyy \* 54 + 一年第几周) % 分表数                                                                              | 拆分键：2012-12-31 分库 ：(2013 \* 54 + 1) % 8 = 7 分表：(2013 \* 54 + 1) % 3 = 1 |
| 分库拆分键 = 分表拆分键(拆分键) | 拆分键：yyyy-MM-dd 分表路由结果 = (yyyy \* 54 + 一年第几周) % (分库数 \* 分表数) 分库路由结果 = 分表路由结果 / 分表数 说明： 分库路由结果四舍五入到最接近的整数。 | 拆分键：2012-12-31 分表 ：(2013 \* 54 + 1) % (8\*3) = 7 分库 ：7 / 3 = 2             |
   
#### 建表语法
假设用户的实例里已经分了8个物理库, 现有一个业务想按年周进行分库。要求同一周的数据都能落在同一张分表，并且两年以内的每个周都单独对应一张分表，查询时带上分库分表键后能直接将查询落在某个物理分库的某个物理分表。
用户这时就可以使用YYYYWEEK分库函数来解决：业务要求两年以内的每个周都对应一张分表（就是一个周一张表），由于一年有近 53 个周(四舍五入)，所以两年至少需要创建 106个物理分表才能满足用户的场景。而用户的DDM有8个分库，所以每个分库应该建14张物理分表（14 \* 8 = 112 \> 106，分表数建议是分库数的整数倍）。建表语法如下所示：
```
create table test_yyyyweek_tb(
id int,
name varchar(30) DEFAULT NULL,
create_time datetime DEFAULT NULL,
primary key(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8
dbpartition by YYYYWEEK(create_time)
tbpartition by YYYYWEEK(create_time) tbpartitions 14;
```
只分库的建表语法：
```
create table YYYYWEEK(
id int,
name varchar(30) DEFAULT NULL,
create_time datetime DEFAULT NULL,
primary key(id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8
dbpartition by YYYYWEEK(create_time);
```
#### 注意事项
- YYYYWEEK算法不支持对于每一个年周都独立对应一张分库，分库分表时必须固定分表数目。
- 当周数经历一个轮回（如2013年第一周是2012年第一周的一个轮回）后，相同周数有可能被路由到同一个分库，请以实际的分库数目而定。
- 使用YYYYWEEK算法时，需要客户端时区和DDM实例时区一致，避免拆分健计算不符合预期。
 
