项目业务中,随着时间推移和业务量的规模变大,原有的数据库表里的数据可能会越来越大,比如说,一个商城系统里,订单数量越来越多,订单表也会越来越大,假设量级到了千万级后,这时候的查询速度就会非常慢,所以就需要各种的优化方案了,现在我要说的就是MySQL分表的水平分表。
一. 什么是分表?
分表有两种形式,一种是水平分表,一种是垂直分表。
1. 垂直分表,也就是“大表拆小表”,基于字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段的字段拆分到“扩展表“。一般是针对那种几百列的大表。
2. 水平分表,也就是“大表拆子表”,和垂直分表有一点类似,不过垂直分表是基于列的,而水平分表是基于全表的。比如说,一个订单表,可以把2019年1月份的订单数据存到一个单独的表里,2月份的数据单独存一个表里,这些表就是“子表”,这些子表一般除了表名的差别,其他结构是完全一致的。水平分表可以大大减少单表数据量,大幅提升查询效率。
二. 操作一下啦
我这里主要是说水平分表的,所以就只有水平分表的实例。
1. MySQL这边的处理
我这里项目里有一个表的量级已经到700w+了,正在往千万量级狂奔,现在而言查询已经有点慢了。
分析下这个表,这个表主要存的是用户安装APP的记录,字段就下面这几个,application_id就是APP的appid,其他字段都是用户的标识字段,
然后我们这样看下这个表,有些application_id的记录已经有100w+的了,所以就可以把application_id很多的这些记录单独拆分到一个表里去,
so!就这样再建几个分别存指定application_id记录的表,就想下面这样的,保持和原表的表结构一致,
然后就可以把原表里的指定的application_id的数据导入到对应的表里,可以用sql实现批量导入INSERT INTO `yy_task_appid_1336013705`(`application_id`, `uid`, `udid`, `idfa`)
SELECT `application_id` ,
`uid`,
`udid`,
`idfa`
FROM `yy_passport_task_appid`
WHERE `application_id` = 1336013705
上面的sql就可以把原表的指定application_id的记录全部插入到新表里了,其他的类似操作就可以啦。
2.逻辑程序这边的处理,程序处理就是如何定位到要用的表,我这里把代码贴出来//appid对应表名的映射
public $AppidTableNameMap = [
'1336013705' => 'yy_task_appid_1336013705',
'1435266708' => 'yy_task_appid_1435266708',
'1261753872' => 'yy_task_appid_1261753872',
'1414156380' => 'yy_task_appid_1414156380',
'1299438106' => 'yy_task_appid_1299438106',
'1334042384' => 'yy_task_appid_1334042384',
'1334612326' => 'yy_task_appid_1334612326',
'others' => 'yy_task_appid_others'
];
//根据appid获取对应的表名
public function getTableName($appid){
$key = isset($this->AppidTableNameMap[$appid]) ? $appid : 'others';
return $this->AppidTableNameMap[$key];
}
//测试代码
public function test($appid){
$table = $this->getTableName($appid);
//后续逻辑...
}
我这里定义一个 appid对应表名的映射容器,然后可以根据appid去获取对应的表名,然后就可以进行其他逻辑处理了
三. 总结
这样一番操作下来,MySQL的水平分表操作其实是很简单的哦!数据库和逻辑两边都相应做好处理就没问题啦,操作虽然简单,但是这样就可以大幅提升查询效率了呀!