使用 PHP 框架开发的产品,在数据量越来越大的时候,发现分表是个很难的工作。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linpf
V2EX    问与答

使用 PHP 框架开发的产品,在数据量越来越大的时候,发现分表是个很难的工作。

  •   linpf 2017-07-15 21:07:05 +08:00 3179 次点击
    这是一个创建于 3009 天前的主题,其中的信息可能已经有所发展或是发生改变。

    产品上线也一年多了,目前数据表中的数据越来越多。由于之前开发的时候,为了追求尽快上线,没有做好长期规划,完全使用了数据模型来进行操作,导致现在需要分表的时候发现难以下手。

    产品是用 tp5 开发的,tp 文档里是有支持分表功能的,但是功能实在是比较弱,无法满足需求。

    这个时候就需要考虑自己去改造业务代码。

    主要需要切分的有用户表、订单表、订单评论表

    其实直接拆分一个表,还是困难不大。但是之前都是用数据模型来操作数据库,如果要拆表的话,发现数据模型改造起来成本太高,需要对架构进行修改。鉴于尽量不修改框架本身的原则,不得不放弃,只能用查询构造器了。

    因为拆表,带来各种的关联也是更加复杂。比如订单评论表本身需要关联订单信息,所以在在每个评论表里都增加 part 和 partId 字段。

    同时用户表的改造带来的问题更多,因为用户表在八成的业务中都用到了,这就意味着带来更多的业务量。幸好之前有一定的封装,但是由于数据模型的操作是利用对象,查询构造器利用是数组,所以需要把所有用户信息修改的地方全部改掉。

    最头疼的地方是,分表是基于项目 ID、用户 ID 进行拆分的,但是有时候需要根据项目表其他字段进行查询的时候,带来的问题就是没有办法在一个表内查询到所有数据。那么我需要再根据要查询的字段再做一个映射表。这样做不但增加了大量的 sql 查询,程序复杂度也大大增加。

    但是我哪怕是做了这个映射表,还是有没有解决的问题。

    一旦我需要 join 查询的时候,映射表就用不到了。这个时候,我只能分别查询所有子表,然后将数据进行整合。

    数据库用的阿里云 RDS,不支持 mrg_myisam(merge)引擎。而且因为考虑到事务的支持,也不考虑 mysql 引擎。

    所以在这里有这几个疑问:

    1、一个听起来很简单的拆表,带来的工作量是不拆表的三到四倍。我实在是想不到有什么更好的办法可以解决这个问题了,希望能够得到大家的意见或者成熟解决方案。

    2、我也查看了一下其他框架对于分表的支持,发现主流框架对于分表支持都不是不友好,那到底利用框架开发的产品,到底能不能支撑起单表超过千万的业务?

    3、如果自己去写一个框架的话,从框架层面,根据自己的业务需求直接解决分表问题就轻松的多了。很好奇是不是大公司都会在数据量到达一定规模的时候,完全放弃通用框架,根据自身业务开发一个框架来重构产品?

    我们产品现在数据量还是几百万,没有达到千万,但是按照现在的数组增长曲线,过千万不会太久。目前产品功能基本上已经定型,问题就是即将面临的性能问题,我是想趁着现在数据量还不大,不会有太大改动成本,提前把改造完成,然后这个产品就可以保持长久一段时间内不改动了,所以不适用于“过早优化是万恶之源”理论,希望大家勿喷。

    15 条回复    2017-07-16 14:08:29 +08:00
    loveyu
        1
    loveyu  
       2017-07-15 21:18:41 +08:00
    有段时间做表迁移,就是把所有的 join 查询全部去掉,然后一张表一张表的改。一百多张,最后就变成了苦力活
    linpf
        2
    linpf  
    OP
       2017-07-15 21:20:10 +08:00
    @loveyu 我现在仅仅是拆订单表,就已经加了 3 个冗余表了。
    shoaly
        3
    shoaly  
       2017-07-15 21:56:22 +08:00
    这个时候 我感觉应该是 专门把数据库 读写操作 替换成 其他 java 等重量级来处理了, 保证 php 那边代码傻白甜.
    changwei
        4
    changwei  
       2017-07-15 22:31:57 +08:00 via Android
    试试看一些流行的数据库中间件呗,顺带还把读写分离等性能优化措施给做好了。
    bazingaterry
        5
    bazingaterry  
       2017-07-15 22:41:11 +08:00 via iPhone
    上数据库中间件吧……
    linpf
        6
    linpf  
    OP
       2017-07-15 22:41:59 +08:00
    @shoaly 即使换做 java 业务逻辑也是一样的。用 java 也并没有什么区别。

    @changwei 公司只有我一个后端,我只能依靠 PHP 来解决问题。
    changwei
        7
    changwei  
       2017-07-15 22:49:17 +08:00 via Android   1
    @linpf 你还是先去百度一下数据库中间件是怎么一回事吧,mysql 好像有个 mycat 听很多人说过,而且这个网上很多实战教程的,实在不行花点钱请个大牛带带你也是好的,了解学习这个东西这个东西对个人成长很有用的。
    guoer
        8
    guoer  
       2017-07-16 00:20:51 +08:00
    用中间件可能花费时间更多,多一层依赖就多了一个出问题的点。
    lshero
        9
    lshero  
       2017-07-16 00:51:23 +08:00
    千万数据的话做表分区就好了啊
    justplaymore
        10
    justplaymore  
       2017-07-16 02:29:41 +08:00
    @guoer 不要去造轮子,造轮子容易,维护才是问题,这种系统底层的东西应该抽象掉,交给中间件去完成,项目代码不应该关心这些事情,大多数老项目总是维护的时间大于开发时间的,我在的公司以前为了节约开发时间,到最后花了十倍的时间去维护,去填坑,这种内部质量绝对不要去妥协。
    linpf
        11
    linpf  
    OP
       2017-07-16 09:46:57 +08:00
    @lshero 网上查了一下,表分区似乎只支持 myisam 引擎
    shoaly
        12
    shoaly  
       2017-07-16 11:04:17 +08:00
    @linpf 只有你一个 那就没办法了. 老老实实 php 吧, 公司也不是你的公司, 就这么着吧...
    我只是说从项目角度上, 单独到 java 上 确实也还要写, 但是好处如下:
    1 让这个本来就不是一个人的活, 分出去, 让更多的人参与进来解决, 而且这个问题就算是专门找人, 也并不是搜搜 google, 就能解决的事情, , 是需要一直持续优化和升级的(假如数据量一直都稳步增长的话)
    2 对于复杂问题来说, java 处理起来比 php 有更容易维护的方式, 也有更多可以 google 借鉴的例子. tp5... 对于现在碰到的问题, 已经到瓶颈了.
    lshero
        13
    lsero  
       2017-07-16 12:21:18 +08:00
    wdlth
        14
    wdlth  
       2017-07-16 13:24:58 +08:00
    你可以先在数据库层次进行考虑,比如分表后,通过在视图中使用 UNION,并且在表加入一些明确的约束去让数据库进行优化,或者你可以搞更高端的存储过程。
    上千万其实并不算多,适当调整统计信息更新频率,数据库参数大小等,查询优化好,一样可以很快。
    你们应该加钱上 DBA 啦……
    akrf
        15
    akrf  
       2017-07-16 14:08:29 +08:00 via Android
    单表体积有多大?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5900 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 06:08 PVG 14:08 LAX 23:08 JFK 02:08
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86