前言
可能有很多朋友在使用CommunityServer(以下简称CS)的过程中,当数据越来越多后,速度会越来越慢,资源耗用越来越大,对于性能不好的服务器,简直像一场噩梦一样,我终于刚刚结束了这个噩梦,简单谈谈是什么原因导致了CS在性能上存在的种种问题。(我对于数据库方面不是很专业,所以如果本文中有什么谬误,敬请各位指出,不胜感谢!)
忘了自我介绍一下,我是宝玉,以前做过Asp.net Forums和CommunityServer的本地化工作,母校西工大的民间社区(http://www.openlab.net.cn)用的是CS系统。该有人骂我做广告了,其实我是防盗版,郭安定大哥那学的,哈哈!
性能问题分析
鸡肋式的多站点支持
其中一个性能影响就是它的多站点功能,也许这确实是个不错的注意:同一个数据库,不同域名就可以有完全独立的站点,但是对于绝大部分用户来说,这个真的有用么?首先姑且不讨论它是否真的那么有用,但是在性能上,他绝对会有一定影响的:系统初始化的时候,首先要加载所有的站点设置,这也是为什么CS第一次访问会那么慢的原因之一;然后大部分查询的时候,都要带上SettingId字段,并且在数据库中,对这个字段的索引并没有建的很理想,对于大量数据的查询来说,如果没有合理的建索引,有时候多一个查询条件对于性能会带来极大的影响。
内容数据的集中式存储
一般的系统,都尽可能的将大量的内容数据分开存储(例如飞信系统的用户存储,就是分库的^_^),对于数据库,更是有专门的分库方案,这都是为了增加性能,提高检索效率。而CS由于架构的原因,将论坛、博客、相册、留言板等内容管理相关的信息,全部保存在cs_Groups(分组)、cs_Section(分类)、cs_Threads(主题索引)、cs_Posts(内容数据),这种架构给代码编写上带来了极大的便利,但是在性能上,不折不扣是个性能杀手,这也是CS慢的最根本原因,举个例子,假如我的论坛有100W数据,博客有5万条数据、相册有10万条数据,如果我要检索最新博客帖子,那么我要去这120万数据里面检索符合条件的数据,并且要加上诸如SettingsId、ApplicationType等用来区分属于哪个站点,哪种数据类型之类的条件,数据一多,必然会是一场噩梦,让你的查询响应速度越来越慢,从几秒钟到几十秒钟到Sql超时。
过于依赖缓存
缓存是个很好的东西,可以大大的减少数据库的访问,是asp.net程序提高性能必不可少的。不知道各位在设计开发系统,用缓存用的很爽的时候,有没有想过,如果缓存失效了会怎么样?如果缓存太大了会怎么样?相信各位CS会有一个感觉,那就是CS刚启动的时候速度好慢,或者使用过程中突然变的很慢,那就是因为好多数据还没有初始化到缓存,例如站点设置、用户资料、Groups集合、Setions集合等等一系列信息,这一系列信息的加载加起来在服务器性能不够好的情况下是个漫长的过程,如果碰巧还要去查询最新论坛帖子、未回复的帖子之类,那么噩梦就开始了,这时候就要拼人品了,看你是不是应用程序池刚重启完的第一个人o(∩_∩)o 。CS在缓存的策略上,细粒度不够,一般都是一个集合一个集合的进行缓存(例如最新论坛帖子集合),这样导致缓存需要频繁更新,而且缓存内的数据一般比较大,内存占用涨的很快,内存涨的快又导致了应用程序池频繁重启,这样,CS在缓存方面的优势反而变成了一种缺陷,导致服务器的资源占用居高不下。
CCS的雪上加霜
前面说过,我做过CS的本地化开发,加了不少CS的本地化开发工作,但是由于当时数据库知识的匮乏,导致了一些在性能上雪上加霜的行为,例如精华帖子功能,其中标志是否为精华帖(精华等级)的ValuedLevel字段没有加上索引,在数据量大的情况下,检索会比较慢。由于我已经不在做CCS的开发,已经没有办法来修正这些性能问题了,只能对大家表示歉意。
后记
如何解决?
最简单就是等着升级了,相信CS以后的版本会越来越强劲的,这些问题肯定会逐步解决的。如果等不及的话,就只能自己动手了,使用Sql Profiler监测Sql的执行,找出影响性能的查询,然后针对性优化。
前面我说我结束CS性能的噩梦,肯定有朋友会问我怎么结束的了,在此,就先埋一个伏笔了,在05年的时候,我就开始如何构思开发一套高性能的类似CS的系统,06年初开始设计,然后利用业余时间进行了具体的开发,到今天已经有了小成,在性能上有了质的飞跃,针对这套系统的设计和性能优化的心得,我会逐渐以博客的形式来和大家一起分享交流。