OneProxy :: 如何配置复合分区?对交易表先按用户分区,再按交易时间二次分片。

当下的互联网公司是不是就宣称有上亿用户量,甚至还有到10亿的,对于用户资料表简单的分片技术将大表一次切小,再将小表分布到多个不同的MySQL数据库中就足够了,比如将一张大的用户表拆分成16张小表。

  {
        "table"      : "user_info",
        "pkey"       : "user_id",
        "type"       : "int",
        "method"     : "hash",
        "partitions" : 16,
        "groups"     : [ "userdb01", "userdb02", "userdb03", "userdb04" ]
  }

OneProxy中执行建表语句(“create table user_info …”),可以发现16张子表会平均分布到四台不同的MySQL服务器中。也可以在在管理端口中直接查看分表的信息,无论有没有真实建表。

mysql> list partitions user_info;
+-----------+--------+--------------+----------+--------+--------+
| TABLENAME | PARTID | PARTITION    | GROUP    | VALUES | STATUS |
+-----------+--------+--------------+----------+--------+--------+
| user_info | 0      | user_info_0  | userdb01 | NULL   | RW     |
| user_info | 1      | user_info_1  | userdb02 | NULL   | RW     |
| user_info | 2      | user_info_2  | userdb03 | NULL   | RW     |
| user_info | 3      | user_info_3  | userdb04 | NULL   | RW     |
| user_info | 4      | user_info_4  | userdb01 | NULL   | RW     |
| user_info | 5      | user_info_5  | userdb02 | NULL   | RW     |
| user_info | 6      | user_info_6  | userdb03 | NULL   | RW     |
| user_info | 7      | user_info_7  | userdb04 | NULL   | RW     |
| user_info | 8      | user_info_8  | userdb01 | NULL   | RW     |
| user_info | 9      | user_info_9  | userdb02 | NULL   | RW     |
| user_info | 10     | user_info_10 | userdb03 | NULL   | RW     |
| user_info | 11     | user_info_11 | userdb04 | NULL   | RW     |
| user_info | 12     | user_info_12 | userdb01 | NULL   | RW     |
| user_info | 13     | user_info_13 | userdb02 | NULL   | RW     |
| user_info | 14     | user_info_14 | userdb03 | NULL   | RW     |
| user_info | 15     | user_info_15 | userdb04 | NULL   | RW     |
+-----------+--------+--------------+----------+--------+--------+
16 rows in set (0.00 sec)

对于用户编号,推荐使用OneProxy的序列号生成功能来生成。用户表可以这样简单地处理,但对于用户相关的其他表,比如交易表、用户日志表等,单个用户每天可能很成很多条记录,只按用户一个唯度拆分还是不够的,随着时间的积累,单个分表可能会变得很大,并且这部份数据不可能永远保持在线,很有可能会按时间做历史数据归档。对于这些表,最好的做法是在按用户分表后,再按时间来做二次切片。在OneProxy中是可以定义二级分区的(请关注“sub”开头的几个属性定义),如下所示:

  {
        "table"         : "user_trade",
        "pkey"          : "user_id",
        "type"          : "int",
        "method"        : "hash",
        "partitions"    : 16,
        "groups"        : [ "userdb01", "userdb02", "userdb03", "userdb04" ],
        "subpkey"       : "create_time",
        "subtype"       : "timestamp",
        "submethod"     : "range",
        "subpartitions" :
           [
               { "suffix" : "_16Q1", "value" : "2016/04/01" },
               { "suffix" : "_16Q2", "value" : "2016/07/01" },
               { "suffix" : "_16Q3", "value" : "2016/10/01" },
               { "suffix" : "_16Q4", "value" : "2017/01/01" }
           ]
  }

这时交易表(暂时取名“user_trade”)就会先按用户号进行分区,然后每个分区再按照交易创建时间(分区列为“create_time”)来做二次分区。在OneProxy管理端口中测试建表语句(“create table user_trade …“),会发现总共需要创建64张表,每个分表都会创建对应的子分区表。

mysql> create table user_trade(...);
+--------------------------------------+
| TABLES                               |
+--------------------------------------+
| create table user_trade_0_16Q1(...)  |
| create table user_trade_0_16Q2(...)  |
| create table user_trade_0_16Q3(...)  |
| create table user_trade_0_16Q4(...)  |
| create table user_trade_1_16Q1(...)  |
| create table user_trade_1_16Q2(...)  |
| create table user_trade_1_16Q3(...)  |
| create table user_trade_1_16Q4(...)  |
......
| create table user_trade_15_16Q1(...) |
| create table user_trade_15_16Q2(...) |
| create table user_trade_15_16Q3(...) |
| create table user_trade_15_16Q4(...) |
+--------------------------------------+
64 rows in set (0.00 sec)

所有的子分区表位于同一个MySQL实例的同一个数据库中,OneProxy的不同的分区表可以位于不同的MySQL实例,但同一个分区的所有子分区表则必须在一起。在这个例子中是按季度来二次分表,也可以改成按月或按天,根据业务的真实情况逐情定夺。分区和子分区的方法可以是“RANGE”、 “LIST”或“HASH”,所以总共可以有9种复合分区的组合。