垂直分表后,完全可由客户端去实现(比如PHP客户端逻辑中去实现),无非是:
原先A表垂直拆分为B、C表
select * from A;
也就变成
select * from B;
select * from C;
把两个结果集合并就是完整的A表记录,垂直分表后还是很好操作的。
那水平分表呢?
即可以由客户端实现(PHP代码写逻辑),也可以在MySQL中实现。
客户端实现(PHP逻辑):
分享一段代码:
大体思路分析:
5行 定义了一个数组,数组元素是四个表名:“student_0”、“student_1”、“student_2”、“student_3”。
7行 一个变量记录的数组个数,为4。
10行 一条SQL语句,意思往“student_id”表插入一个null数据,目的只是在11行获取一个主键ID。
12行 通过“ID%4”求余,作为数组的一个下标去获取一个表名。
14行 往获得的表里插入数据。
这样很简单地就可以实现水平分表功能了。
当然我们不仅可以按照ID取模分表,也可以按照数据的时间分表、ID区间范围分表或者通过某个数据的hash值分表……
MySQL中实现:
当我们要分表时,往往都是数据量很大的时候需要水平分表。有时候可能觉得受牵连的代码太多了,为了实现分表功能而去修改很多很多代码不值得。那也没问题,也有不用动业务代码就可以实现水平分表的方法。
分表后,如果不想客户端(比如PHP)自己做判断该操作哪个表,由MySQL智能去完成,也是可以的。
说两种方法:(如果楠神要分表会选择由PHP逻辑代码实现分表功能,楠神也没有实际操作过在MySQL中开启智能分表,以下内容大家可做参考学习)
1)partition分区:
将某张表数据,分别存储到不同的区域中。
其实:每个分区,就是独立的表。都要存储该分区数据的数据,索引等信息。
创建分区:
在创建表时,指定分区的选项:
Create table table_name (
定义
)
Partition by 分区算法 (参数) 分区选项。
Tip:分区与存储引擎无关,是MySQL逻辑层完成的。
通过变量查看当前mysql是否支持分区:
分区算法:
MySQL提供4种
取余:Key,hash
条件:List,range
提示,参与分区的参数字段需要为主键的一部分。
按照某个字段进行取余
按照某个表达式的值进行取余
学生表分区,按照生日的月份,划分到12个表中。
Tip:
Key,hash都是取余算法,要求分区参数,返回的数据必须为整数。
需要指定的每个分区数据的存储条件。
按照生日中的月份,分成春夏秋冬四个分区。
List,条件依赖的数据时列表形式。
Range:条件依赖的数据是一个条件表达式。
逻辑:按照生日的年份分成
增加分区数量:
Add partition N
减少分区数量:
COALESCE partition N
采用取余算法的分区数量的修改,不会导致已有分区数据的丢失,需要重新分配数据到新大地分区。
添加分区
删除分区:
Drop partition partition_name;
注意:删除条件算法的分区,导致分区数据丢失。
平均分配: 就按照主键进行key(primary key)即可(非常常见)
按照某种业务逻辑分区: 选择那种最容易被筛选的字段,整数型
2)利用merge存储引擎来实现分表
MySQL提供一个可以将多个结构相同的myisam表,合并到一起的存储引擎——merge:
从上面的操作中,不知道你有没有发现点什么?假如有一张用户表user,有50W条数据,现在要拆成二张表user1和user2,每张表25W条数据,
INSERT INTO user1(user1.id,user1.name,user1.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id <= 250000
INSERT INTO user2(user2.id,user2.name,user2.sex)SELECT (user.id,user.name,user.sex)FROM user where user.id > 250000
这样成功的将一张user表,分成了二个表,这个时候有一个问题,代码中的sql语句怎么办,以前是一张表,现在变成二张表了,代码改动很大,这样给程序员带来了很大的工作量,有没有好的办法解决这一点呢?办法是把以前的user表备份一下,然后删除掉,上面的操作中我建立了一个alluser表,只把这个alluser表的表名改成user就行了。但是,不是所有的mysql操作都能用的
a,如果你使用 alter table 来把 merge 表变为其它表类型,到底层表的映射就被丢失了。取而代之的,来自底层 myisam 表的行被复制到已更换的表中,该表随后被指定新类型。
b,网上看到一些说replace不起作用,试了一下可以起作用的。
c,一个 merge 表不能在整个表上维持 unique 约束。当你执行一个 insert,数据进入第一个或者最后一个 myisam 表(取决于 insert_method 选项的值)。mysql 确保唯一键值在那个 myisam 表里保持唯一,但不是跨集合里所有的表。
d,当你创建一个 merge 表之时,没有检查去确保底层表的存在以及有相同的机构。当 merge 表被使用之时,mysql 检查每个被映射的表的记录长度是否相等,但这并不十分可靠。如果你从不相似的 myisam 表创建一个 merge 表,你非常有可能撞见奇怪的问题。