PHP做数据统计分析

时间:2022-07-23
本文章向大家介绍PHP做数据统计分析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前段时间的主要工作是开发统计系统, 统计公司产品的安装量和回访量,统计数据则由客户端调用C接口写入mysql数据库,即我们只需要分析客户端写入的原始数据即可。下面是对这个项目的一个总结:

系统评估

  • 1、预估当前每天的回访量有大几百万,随着其它产品的不断推广, 要统计的数据可能越来越多。
  • 2、统计的数据有比较强的约束关系。对于一条安装数据,必须判断之前唯一安装表中是否存在该记录, 若存在则再根据版本判断升级或重装,否则为新装数据,回访数据类似逻辑。所以,如果要出按小时统计数据,则必须把前一个小时数据处理完之后才可以处理后面的数据;前一天的数据处理完之后才可以处理后一天的数据。
  • 3、团队中都擅长的是PHP。hadoop或其他大数据处理方式经验薄弱,面临学习成本和一些未知因素。

所以最终还是选择用PHP+Mysql来统计,前期应该可以撑一撑。

接下来对每个步骤进行梳理:

  • 1、C接口直接写数据到安装表和回访表,原始数据的表采用按年分表,按天分区。原始数据量比较大,也不适合PHP写入。
  • 2、转移数据。原始表记录数比较多,为了尽可能的减少与原始表的耦合,这里做了一个转移的动作,将原始表的最新安装、回访数据转移到近期安装、回访表中。近期表只保留3天的数据,即近期回访表的数据会维持在2000w左右。这个动作是否可以用触发器来完成?这里没有采用触发器,个人始终认为触发器和业务依赖太紧,当原始数据需要调整时触发器也要相应调整,觉得不是很方便,因为修改触发器势必会影响写入操作。
  • 3、数据更新。因为需要一条一条判断数据为新装、重装或者新用户、老用户,区域等,所以有这个更新的过程,更新每一条记录的状态。这里将可能是系统瓶颈所在。
  • 4、小时报表。 数据更新完之后即可根据该数据出报表,因为统计的字段8个左右,所以累计到一定时间之后,这个表的数据也将会很多,前台不适合直接从这里取报表数据。
  • 5、其他报表。 可根据小时报表出天的报表,或者出特定字段的报表等等,这是很方便的,同时数据量也将成倍的减少。

系统实现

项目使用CI开发,实现的步骤就没太多说的,查询的时候注意下索引的先后顺序就行了,系统到目前还没出现因不中索引而引起的问题。不过程序上的一些调整可以记录下:

  • 1、 报表采用highchart实现,但最开始是直接在控制器获取到报表数据后传到视图,当一个页面有多个报表的时候需要把这些数据一次性读取出来之后页面才会显示。运行了一段时间发现打开慢,也不方便扩展,所以把报表统一改成了ajax调用。
  • 2、 菜单的调整。最开始未意识到后面有更多的产品移植过来,所以对菜单也进行过一次调整。
  • 3、 crontab的调整。最开始所有的crontab脚本都放置在一个控制器中,随着不断的增加发现越来越难控了,难以按产品区分,有些也不用了。为了理清这些脚本以及执行频率,对这里- 进行了一次调整。
  • 4、主从调整。运行一段时间后增加了个从库(32G),所有查询的操作从从库拿,调整之后前台报表表现明显。
  • 5、模型的调整。 这个还未深入调整^_^,因为有新老系统的原因, 模型太多,以及很多业务逻辑写在模型中,模型很重。

上面的每一个调整并不需要多少时间, 但对不段增长的系统是很有好处的,每当它要倾斜时,我们就把它扶正,希望它能坚持更久一点。

系统新增功能和调整

调整用户唯一ID。

IOS产品原先用uuid来判断唯一性,但7.0之后发现uuid不唯一了,所以统计系统部分产品要将唯一值由uuid替换为序列号,但一直以来都是uuid为唯一ID,统计这边也直接以uuid为唯一键了。这意味着唯一键要调整,大部分表结构都需要调整了。

原始表有的有序列号,有的没有,所以首先是原始表统一增加序列号字段,因为转移的数据只将特定的字段值写进去,所以原始表的调整对统计不会有影响。同时原始表已有2.5亿数据,直接调整表结构基本不可能。所以采取新建一张调整后的表,rename一下即可,rename的过程是很快的,rename之前的几千条未转移的数据再手动转移一下。

统计这边将在近期表新增一个唯一字段, 唯一字段不依赖固定值。因为即便调整了, 有一些产品还是以uuid为准,唯一值在转移的过程中判断即可。 统计系统调整时先停下所有的脚本,近期表直接删除重建即可,唯一表因为需要处理,边转移边处理一下即可,报表数据保留原有。所以整个过程下来调整并不算大,只是因为数据量比较大,处理觉得麻烦一点而已。

增加一个产品

系统中已经增加了好几个产品了, 这里增加产品的接口是用php实现的。即客户端调用php页面,php写数据库,回访数据大概每天100w左右。运行几天后发现php接口机器挂了, nignx进程数太多。原因就是统计系统比较忙时,数据库压力比较大,php一条一条写入很慢, 很多进程都在等待,于是爆了。。。

针对这个问题的处理方法是,php接口直接写数据到文本,然后脚本定时load数据到数据库。

历史数据处理

有个产品需要对历史数据进行重新统计,历史数据有1亿多。因为历史数据和新数据之间的字段、值等需要进行一次处理,所以采用 SELECT INTO OUTFILE的方式导出,1.6亿数据中导出1.2亿大概5分钟左右。导出之后的的文件有9G左右,直接一次LOAD mysql会超出binlog的限制。所以设置了binglog为3G,然后对原数据按每1000w行进行切割,在一个个导入。

如果导入的表已经建好索引,开始导入1000w要半个多小时,导入了4000w数据后发现奇慢无比。后来重新导,导入的表未建立索引,1000w数据大概需要9分钟左右。不过后来增加索引花了大概2个半小时。

对原始数据的处理也是一个问题,为了提升效率,比较大的数据采用多进程跑,比如开10多个进程同时跑一个小时的数据,二三十万数据3分钟就搞定。但当系统中的这些进程碰到一起时,系统就开始慢了, 所以只能用程序去控制下。

系统总结

1、 到目前位置系统运行还算正常,但随着新功能的不断增加,这也是个挑战。如果只是针对单个产品,一般的业务,用php来处理,日2000w数据问题应该不是很大。

2、系统监控。到目前位置做个几个统计系统了,前面一个是最完善的,有很多监控,可以很快发现问题。当前这个系统数据量是比较大的,但监控还比较薄弱,或者已经有很多潜在的问题被忽略,所以做好监控是有必要的。

3、 使用php运行crontab要防止脚本重复执行,限制起来也很简单,可以用php的exec函数去查看一下当前脚本是否正在执行(需要服务器未限制exec函数),如果正在执行就直接退出,给个简单的判断方法:

function get_process_num($process_name) { return exec('ps -ef | grep "'.$process_name.'" | grep -v "grep" | wc -l'); }