原博文出自于: http://blog.fens.me/category/%E6%95%B0%E6%8D%AE%E5%BA%93/page/5/ 感谢!
select count(*)的思考
原文:MYSQL性能调优与架构设计
举例:
这里我们就拿一个看上去很简单的功能来分析一下。
需求:一个论坛帖子总量的统计
附加要求:实时更新
在很多人看来,这个功能非常容易实现,不就是执行一条SELECT COUNT(*)的Query 就可以得到结果
了么?是的,确实只需要如此简单的一个Query 就可以得到结果。但是,如果我们采用不是MyISAM 存储引擎,而是使用的Innodb 的存储引擎,那么大家可以试想一下,如果存放帖子的表中已经有上千万的帖子的时候,执行这条Query 语句需要多少成本?恐怕再好的硬件设备,恐怕都不可能在10 秒之内完成一次查询吧。如果我们的访问量再大一点,还有人觉得这是一件简单的事情么?
既然这样查询不行,那我们是不是该专门为这个功能建一个表,就只有一个字段,一条记录,就存
放这个统计量,每次有新的帖子产生的时候,都将这个值增加1,这样我们每次都只需要查询这个表就可以得到结果了,这个效率肯定能够满足要求了。确实,查询效率肯定能够满足要求,可是如果我们的系统帖子产生很快,在高峰时期可能每秒就有几十甚至上百个帖子新增操作的时候,恐怕这个统计表又要成为大家的噩梦了。要么因为并发的问题造成统计结果的不准确,要么因为锁资源争用严重造成整体性能的大幅度下降。
其实这里问题的焦点不应该是实现这个功能的技术细节,而是在于这个功能的附加要求“实时更
新”上面。当一个论坛的帖子数量很大了之后,到底有多少人会关注这个统计数据是否是实时变化的?有多少人在乎这个数据在短时间内的不精确性?我想恐怕不会有人会傻傻的盯着这个统计数字并追究当自己发了一个帖子然后回头刷新页面发现这个统计数字没有加1 吧?即使明明白白的告诉用户这个统计数据是每过多长时间段更新一次,那有怎样?难道会有很多用户就此很不爽么?
只要去掉了这个“实时更新”的附加条件,我们就可以非常容易的实现这个功能了。就像之前所提
到的那样,通过创建一个统计表,然后通过一个定时任务每隔一定时间段去更新一次里面的统计值,这样既可以解决统计值查询的效率问题,又可以保证不影响新发贴的效率,一举两得。
实际上,在我们应用的系统中还有很多很多类似的功能点可以优化。如某些场合的列表页面参与列
表的数据量达到一个数量级之后,完全可以不用准确的显示这个列表总共有多少条信息,总共分了多少页,
而只需要一个大概的估计值或者一个时间段之前的统计值。这样就省略了我们的分页程序需要在分以前实时COUNT 出满足条件的记录数。
其实,在很多应用系统中,实时和准实时,精确与基本准确,在很多地方所带来的性能消耗可能是
几个性能的差别。在系统性能优化中,应该尽量分析出那些可以不实时和不完全精确的地方,作出一些相应的调整,可能会给大家带来意想不到的巨大性能提升。