最近代码上生产环境上后,发现性能严重下降,计算一个设备之前只需几百毫秒,现在需要几秒甚至十几秒了,如果平均一个10s,4w个设备4个线程计算需要27小时,这样肯定不行
查看监控面板,发现cpu使用很低,之前计算的时候cpu要200%多,现在只有50%不到
说明瓶颈不是cpu,那基本就是IO了
通过arthas,找到耗时最多的方法是getPreviousDataFromInflux,这个方法是每计算一个参数时,从influxdb读取该参数的前一个值,执行的语句大概是:
select last("DI14") as raw, "-diff_acc_param-DI14" as diff, "-acc_param-DI14" as acc from device_data WHERE device::tag = 'AM19050363' and time < '2024-10-17T00:00:00Z'
之前在测试环境,查一次只需要几毫米到10几毫秒,现在生产环境需要100ms左右。
为什么两套环境查询耗时差距这么大?是不是生产环境数据库有问题?
虽然两者数据磁盘占用都是1个多T,但是在时间上的分布不同,测试环境都是最近几个月的数据,而生产环境则是几年的数据,而inflxdb的压缩机制,越老的数据压缩比越高,从而查询的越慢。
再来看这条语句select last where time < T,之前以为它只需要从指定的时间往前找就行了,但是其实不是这样,他需要先找出time < T的所有数据,再从中找出时间最新的
那么在生产环境下,就需要找几年的数据,而且这些数据还是高级别压缩的数据,查找效率肯定慢了,所以这条语句耗时100ms属于正常
如何优化:
第一招,减少查询次数,之前是一个参数查一次,改为1个设备查一次,这样查询次数减少了几十倍
实测效果不理想,虽然查询次数少了,但是每次查询耗时增加了
第二招,减少查询时间范围,time < T 的时间范围可能是几年,太大了。改为T1<time < T2,
时间范围控制在1年内。测试发现有一些效果,但还不够
第三招,考虑到大部分情况下,我们要查的数据在3天以内,因此我们改为分2次查询,先查3天内的,如果没查到(只有1%)再查1年的数据。
实测效果很好,问题解决