MySQL数据库优化之大数据表的水平分表

2019-04-22 17:31:50 PHP 阅读 (3698) 评论(0)

        项目业务中,随着时间推移和业务量的规模变大,原有的数据库表里的数据可能会越来越大,比如说,一个商城系统里,订单数量越来越多,订单表也会越来越大,假设量级到了千万级后,这时候的查询速度就会非常慢,所以就需要各种的优化方案了,现在我要说的就是MySQL分表的水平分表。


       一. 什么是分表?

分表有两种形式,一种是水平分表,一种是垂直分表。

            1. 垂直分表,也就是“大表拆小表”,基于字段进行的。一般是表中的字段较多,将不常用的, 数据较大,长度较长(比如text类型字段的字段拆分到“扩展表“。一般是针对那种几百列的大表。

               2. 水平分表,也就是“大表拆子表”,和垂直分表有一点类似,不过垂直分表是基于列的,而水平分表是基于全表的。比如说,一个订单表,可以把2019年1月份的订单数据存到一个单独的表里,2月份的数据单独存一个表里,这些表就是“子表”,这些子表一般除了表名的差别,其他结构是完全一致的。水平分表可以大大减少单表数据量,大幅提升查询效率。

        二. 操作一下啦

            我这里主要是说水平分表的,所以就只有水平分表的实例。

           1. MySQL这边的处理

          我这里项目里有一个表的量级已经到700w+了,正在往千万量级狂奔,现在而言查询已经有点慢了。

image.png

      分析下这个表,这个表主要存的是用户安装APP的记录,字段就下面这几个,application_id就是APP的appid,其他字段都是用户的标识字段,

image.png


        然后我们这样看下这个表,有些application_id的记录已经有100w+的了,所以就可以把application_id很多的这些记录单独拆分到一个表里去,

image.png

        so!就这样再建几个分别存指定application_id记录的表,就想下面这样的,保持和原表的表结构一致,

image.png

             然后就可以把原表里的指定的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的水平分表操作其实是很简单的哦!数据库和逻辑两边都相应做好处理就没问题啦,操作虽然简单,但是这样就可以大幅提升查询效率了呀!




评论