OneProxy :: 分库分表中对日期类型做Hash分区时,数据是如何分布的?

可以在OneProxy使用做Hash类型的分库分表,当分区键是字符串类型(“CHAR”)时,会使用OneProxy内部的一个Hash函数来计算出一个正数,然后按这个数据去定位分区;当分区键是整数类型(“INT”)时,将会转换成正数,然后直接用来定位分区。对于哈希分区,最后得到的数字去余一下分区的个数,就是分区的位置了。那么Hash分区时,分区键为日期类型(“DATE”或“TIMESTAMP”)时,又如何处理呢?象“2016-1-1”和“2016-01-01”两种不同的写法,从字符串的角度来讲是不同的值,而从日期的角度来讲则是同一天,因此不能直接应用前面的Hash函数,而是将日期转换成从公元第一天以来的天数,然后用这个天数去余分区数来进行分区定位。

比如我们在OneProxy中有如下一个分区表的定义。

  {
        "table"      : "my_datehash",
        "pkey"       : "id",
        "type"       : "timestamp",
        "method"     : "hash",
        "partitions" : 4,
        "groups"     : [ "server1" ]
  }

在OneProxy中发送创建表的命令。

mysql> create table my_datehash
    ->    (id date not null primary key, col2 int);
Query OK, 0 rows affected (0.07 sec)

然后再来插入几条记录(这些记录具有相同的日期,但时间点不同)。

mysql> insert into my_datehash (id, col2)
    ->     values ('2016-03-26 16:48:33', 100);
Query OK, 1 row affected (0.00 sec)

mysql> insert into my_datehash (id, col2)
    ->     values ('2016-03-26 16:49:00', 200);
Query OK, 1 row affected (0.00 sec)

在OneProxy里可以使用“SHOW PARTITION 表名 分区键 值”来查询某个值所在的分区表的表名(设计这个功能是方便进行数据清理,比如今天可以清理掉明天将要用到的分区)。

mysql> show partition my_datehash id '2016-03-26 16:49:00';
+---------------+
| Partitions    |
+---------------+
| my_datehash_1 |
+---------------+
1 row in set (0.00 sec)

接下来查一下表分片(“m_datehash_1”)里的数据,可以看到所有属于同一天的记录都被放在同一个分片中了。

mysql> select * from my_datehash_1;
+---------------------+------+
| id                  | col2 |
+---------------------+------+
| 2016-03-26 16:48:33 |  100 |
| 2016-03-26 16:49:00 |  200 |
+---------------------+------+
2 rows in set (0.00 sec)

针对“DATE”或“TIMSTAMP”类型的Hash分区表,并不是真正的Hash分区,而是转换成了按天分区,数据并没有真正地打散。现在再来插入几条记录,将日期更改变4天(刚好是分区数量)以后,看看这些分区会位于哪个分片呢?可以想象出来,应当位于同一分片。

mysql> insert into my_datehash (id, col2)
    ->   values ('2016-03-30 16:48:33', 100);
Query OK, 1 row affected (0.01 sec)

mysql> select * from my_datehash_1;
+---------------------+------+
| id                  | col2 |
+---------------------+------+
| 2016-03-26 16:48:33 |  100 |
| 2016-03-26 16:49:00 |  200 |
| 2016-03-30 16:48:33 |  100 |
+---------------------+------+
3 rows in set (0.00 sec)

由于分片总数是4个,因此4天以后的记录将和今天的数据位于同一个分片中。这将方便你创建有固定保留期限的分区表,比如业务上要求保留最近90天的完整数据,则只需要创建一个具有92个分片的Hash表,一个分区用来作为当前写入,不算完整的一天,一个空分区用来作下一个周期的数据写入。

  {
        "table"      : "my_datehash",
        "pkey"       : "id",
        "type"       : "timestamp",
        "method"     : "hash",
        "partitions" : 92,
        "groups"     : [ "server1" ]
  }

针对历史表,或者可以定期清理的大表,这个功能可以让你很方便地创建分区表,然后布署一个定时作务,来每天清空下一天(下个周期)所在的分区,就可以不用担心空间的无限增长了。