PHP数据导出功能优化案例

2 篇文章 0 订阅
1 篇文章 0 订阅

  本文以一个Excel表单导出功能的演化路线为示例,分享导出任务的通用模式、Reactor和Worker分离的思路等经验。

演示代码请移步Github:PHP-export-optimize

版本1:快速上线

  为了快速上线,代码写的比较粗糙,一般导出2000多条记录的表格,应用就已经爆掉了(执行时间超时或者内存超限)。
  简单的通过分配更多的资源,就可以临时的满足要求。比如,增大PHP请求的允许占用内存等。但是,随着业务的快速发展,这种简单粗暴的方法很快就不能满足需求了。
  在给出的示例中,导出10000条记录,内存就已经不够用了。

Allowed memory size of 134217728 bytes exhausted (tried to allocate 147456 bytes)

  当然了,这个极限值,也是根据机器的性能,SQL执行的情况等因素而定的。一般情况不超过10000条。

版本2:精耕细作

  优化,无非就是找冗余:执行时间的冗余,存储空间的冗余。
  通过在各个环节打桩记录,比较执行时间和内存占用,找出瓶颈,然后设计相应的方案。

优化SQL

  • 列表内容
  • 去除不必要的字段;
  • 采用分页的形式,削峰;

优化文件操作

  • 索引优化;
  • 改用资源占用更少的文件格式(csv);
  • 文件读写时,使用缓冲的方式;

语法层面

  • 减少不必要的临时变量的使用;
  • 关注垃圾回收的情况;

此时,最大导出记录数可以达到上万的级别。

版本3:异步执行

  个人认为,web请求的执行不应该超过两分钟,因为web请求应该是快速响应的,同步的。相对耗时的任务,应该交给守护进程或定时任务来完成。在SQL很复杂、很耗时的场景下,同步执行再怎么优化也会达到比较明显的上限。,就应该考虑使用异步的方式。比如消息队列或RPC调用。
  本文结合swoole进行讲解。无论是使用swoole实现RPC调用,抑或是通过消息队列进行解耦。执行查询任务的worker始终是需要设为守护进程的。而前端也存在一个缺陷,那就是需要不停的轮询后台来获取任务执行进度。

版本4:主动反馈

  通过前面的改造,我们已经大大提升了记录导出条数的上线。但是我们又遇到一个新的问题。轮询的任务如果太多的话,会给数据库带来较大的压力。如果不去查询任务执行情况,用户又无法及时获得任务的执行状态。对于一些实时性要求比较高的任务,比如导出的是财务有关的数据,用户希望及时看到执行结果。
  此时,我们可以通过在前端使用websoket与后台保持长连接,当导出任务执行完成时(进度条进入下一个环节时),通过消息队列或其他方式,将执行结果广播给用户。

参考文献:
1. Thinkphp5文档官方
2. swoole官方文档

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值