写在前面
- 为什么要分表呢?这个看似不是问题的问题先埋个点
进入主题吧
**ps: 这里只分享一下业务上面进行分表的一些方法吧
一. 垂直分表
垂直分表在业务开发过程中应该是随处可见的,比如:用户相关的表
CREATE TABLE `user` (
`uid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(50) DEFAULT '' COMMENT '用户登录名',
`password` char(32) DEFAULT '' COMMENT '用户登录密码',
`is_del` tinyint(1) unsigned DEFAULT '1' COMMENT '1,正常 2,删除',
`create_time` char(10) DEFAULT '0' COMMENT '录入时间',
`update_time` char(10) DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户基本表';
CREATE TABLE `user_info` (
`uid` int(11) unsigned NOT NULL,
`head_img` varchar(50) DEFAULT '' COMMENT '头像',
`nick_name` varchar(50) DEFAULT '' COMMENT '昵称',
`sign_content` varchar(255) DEFAULT '' COMMENT '个性签名',
`update_time` char(10) DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`uid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
......
如上所见,垂直分表就是把一个实体按照某种属性进行分类划分成多个表。
.
二.水平分表
1. 范围取表方式
比如用户联系信息: 我们可以按照范围分表
1-100w: user_info_1 100w-200w: user_info_2
CREATE TABLE `user_info_{{1+}}` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL DEFAULT '0' COMMENT '用户uid',
`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号',
`address` varchar(50) NOT NULL DEFAULT '' COMMENT '住址',
......
`is_del` tinyint(1) unsigned DEFAULT '1' COMMENT '1,正常 2,删除',
`create_time` char(10) DEFAULT '0' COMMENT '录入时间',
`update_time` char(10) DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uid_index` (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户联系信息表';
.
2. 特定的算法分表(取模、哈希)
取模:比如用户ID%100,分100张表
CREATE TABLE `visit_record_{{1-100}}` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL DEFAULT '0' COMMENT '所属人uid',
`source_id` int(11) NOT NULL DEFAULT '0' COMMENT '资源id',
`type_mark` int(10) NOT NULL DEFAULT '0' COMMENT '资源类型',
......
`create_time` char(10) DEFAULT '0' COMMENT '录入时间',
`update_time` char(10) DEFAULT '0' COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `st_index` (`source_id`,`type_mark`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户资源访问记录';
优缺点:
取模方式:
冷热数据比较均衡,但扩展性比较差,一但数据量超过预期,原定表数量就无法承载,再加表就比较麻烦
范围方式:
扩展性比较强,但是一般新用户是比较活跃的,大部分都查询到新表上面,就导致冷热数据不均衡要解决这样的问题可以两者结合互补, 首先根据范围进行分组: 比如用户1~1000w,分为10张表,然后 uid%10 得到具体表、相当于1-10表的总数据量已经确定了,先取范围再取模,扩展性问题就不存在了