V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
linpf
V2EX  ›  问与答

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

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

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

    产品是用 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
    lshero  
       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   ·   实用小工具   ·   2618 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 11:23 · PVG 19:23 · LAX 03:23 · JFK 06:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.