步骤前端
a. 分析业务场景
该表的使用者为签到用户和运营人员。
签到用户进行签到时在表中记录的相关信息:uid、时间、ip等。签到用户侧对数据库使用的基本特色是:单条记录写入,访问量大,服务要求高可用。
运营人员在前端经过uid查询用户的签到信息,业务场景如:用户投诉某天的签到没有统计。运营人员侧需求的基本特色是:大量的批量分页查询需求,或许须要增长多种查询方式。mysql
c. 方案设计:
采用水平分表的方式,按照时间或uid进行分表。
按照时间:好比半年
优点:1.扩容简单,只需按照时间增长表便可;2. 查询的数据为近期数据,只需在一个表中按照近期时间查询便可;3.切分策略简单;4.须要修改部分写入和查询的代码:写入操做须要按照时间更新,查询操做须要根据查询数据量进行多表查询。
劣势:1.请求量不均,老是在新表写入数据;2.当须要查询用户全部签到数据时须要访问全部表,时间慢;3.数据量不均,新增的表数据量会很是少。
由于劣势2不选择此方案,有1000多个用户签到时间超过600天,证实存在一直签到的用户,那么若按时间分配查询他们的会比较慢。查询逻辑会多写一部分代码。请求量和数据量均比较小,此两项能够不考虑
按照uid:
哈希法
优点:1. 数据量均衡;2.请求量均衡。
劣势:1.扩容麻烦,若增长新表则需从新哈希,可能会致使数据迁移;2. 写入操做须要更新按照uid哈希结果进行写入,查询操做须要按照uid哈希结果进行查询。若增长新表则需修改代码。
选择此方案:对3取余扩容会在两年后进行,不管采用什么方案都会修改代码
范围法
优点:1.策略简单;2.扩容简单。
劣势:1.数据量不均;2.不方便增长新用户,如今才4万左右,若增长新用户可能须要增长新表。sql
最终结果:哈希法(对3取余)
采用此方案的缘由:
数据分布均匀,表中数据对3取余后,各个字表中数据量分布均匀,数据增加量分布均匀,按照目前的增加速度大概两年后每一个字表中的数据达到1000万。
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 0 and create_time > 1532238674000 and create_time < 1533189074000;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 14105 | 66926 |
+---------------------+------------+
1 row in set (14.55 sec)数据库
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 1 and create_time > 1532238674000 and create_time < 1533189074000;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 13994 | 66237 |
+---------------------+------------+
1 row in set (14.46 sec)ui
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 2 and create_time > 1532238674000 and create_time < 1533189074000;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 13964 | 66300 |
+---------------------+------------+
1 row in set (17.93 sec)设计
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 0;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 346305 | 5288253 |
+---------------------+------------+code
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 1;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 345785 | 5324079 |
+---------------------+------------+ip
mysql> select count(distinct uid),count(uid) from user_*** where uid % 3 = 2;
+---------------------+------------+
| count(distinct uid) | count(uid) |
+---------------------+------------+
| 346966 | 5328743 |
+---------------------+------------+select
d. 执行方案 (1)在保证用户正常使用的前提下,对数据库进行分表。须要在维持旧表的同时,让数据双写,同时写入新表和旧表,此时让数据往新表导入。