刚开始写纸飞机的办公系统,里面有两个地方需要实时更新:维修队列和签到列表。后台用的是PHP嘛,所以前台肯定是用AJAX轮询了。刚开始接触AJAX不久,于是就很脑残地想到了一个思路——每隔3秒AJAX一次,每次返回一个完整的列表信息,然后前台用innerHTML更新。很凶残很暴力,后果嘛——每天云豆消耗大概在20~40左右吧。
后来尝试压缩xhr的请求和返回数据大小,发现效果不明显。直到我有一次特意看了看云豆消耗……
于是心里十分地卧槽……赶紧想办法减少一下数据库的消耗吧。
首先,数据库语句好像没什么可优化的。于是我就开始找计费更低的服务。把SAE的计费方式看了个遍,发现其余可以存储数据的服务也好贵啊。
(目测好多大神看到这里已经把我鄙视的很爽了……)
然后无意中想到了可以利用MAX(id)作为状态,于是就有了如下的思路:
每次请求的时候带上一个lastID,然后后台SELECT MAX(id),如果比lastID大则返回更新的数据,否则直接返回空。
方法很有效,对于一个平时每天只有最多几十个人用的系统,状态变化很少,所以绝大部分的AJAX其实都是无效的,那么现在只需要查一遍MAX(id),跟以前返回所有数据相比,云豆消耗当然变少了。
(有经验的人一般第一想法就是这个吧?)
直到蛋蛋晚会那天,我的SAE上还需要挂着飞机墙和晚会直播弹幕的AJAX接口,这下可好,一堆人疯狂地向服务器POST数据,我这点云豆怎么能受得了……果断要继续优化,争取精简掉任何多余的数据库查询!
飞机墙也好直播弹幕也好,对于所有人来说都是同步的,因此同一时刻,所有人询问MAX(id)的值应该是完全一样的。那么——SAE里面有个Counter,说白了就是一个键值对,只不过值必须是普通整数。不过它有一个最大的优势:免费!于是思路又来了。
在Counter中设置一个叫MaxPwFloor(名字随意)的值,一开始为0,然后修改上墙相关的代码:在将用户上墙信息插入数据库之后立即将这个值+1。这样连MAX(id)都用不着了,几乎所有的数据库查询都是有效的。
考虑到用户签到也是在所有电脑上同步的,因此也可以用一个值来记录当前签到用户的MAX(sign_id),如果传进来的lastSignID不如它大,就返回lastSignID与MAX(sign_id)之间的所有签到记录。
效果嘛,当然是相当明显的啦:
时刻想一想,自己的思路是不是有点暴力,有没有优化空间,既是为用户流量着想,也是让自己的云豆花在该花的地方。(此处应该@Coding)
P.S.此方法仅适用于返回数据的状态在同一时刻对所有用户都相同的情况。