你的老板或客户是否曾和你抱怨公司的网站性能愈来愈差?网站大家都会写自从有了 Visual Studio 之后连你家楼下的正妹小喵和隔壁的王大婶都会写 ASPNET但同样的一个画面背后的性能却可能是天差地远更惶论多人同时上线的企业网站而程序员的身价也因此有所差别本帖提供一些改善网站性能的点子从硬件软件程序技巧的层面都有也欢迎大家分享自己的经验或秘技 () 重新调整或重新设计 DB schema索引 (index) 一个在线系统的性能不佳主要原因都是来自于数据库规划及 SQL 语句层面至于 NET 程序撰写不良都还在其次 先将数据库适度地做正规化如一个 Table 中避免把常用的字段很少用的字段都塞在同一个表中而影响数据扫描的速度 应该将很少用的字段另切割出来成为另一个表 () 改写 SQL 语句注意 index 是否在查询时有真的被用到 * 同样的功能一个不良的「关联子查询」和良好的「独立子查询」之间的 SQL 性能差距是不到一秒钟和好几分钟以上的差距 * 一些 SQL 关键词只要一出现在 SQL 语句中就可能造成表的「索引 (index)」完全失效或部分失效变成要整个表去逐行逐列地扫描 例如: NOTNOT IN!=<>OR 等关键词 还有「LIKE %关键词」的模糊查询也会造成索引失效但「LIKE 关键词%」就不会造成索引失效 () 使用 Native 的 DataProvider 放弃 OleDb改用 ADONET Native 的 DataProvider如: SqlClientOracleClient但若您公司坚持要用 Sybase 这种从 年之后就不曾更新 DB driver 的数据库就只好继续用性能不佳的 OleDb 去联机了 据版工我用 Visual Studio 内建的 stress test 工具测试 OleDb 和 SqlClient 的性能差距模拟 人同时上线用浏览器撷取一万笔数据两者的速度就差了一秒钟且当数据库的数据越多或越多人同时上线时性能差距会更明显 () 用程序或软件做缓存 用程序做缓存如 ASPNET 从 x 时代就已内建的 Cache (缓存) 机制或用一些第三方的辅助软件Framework这方面若有其它网友知道好用的软件亦恳请留言告知 () 用硬件做快取或缓沖砸钱加装 AP Server ITHome 游戏基地网页效能提升的关键人物 以下引用自原文: 种种缺失使得网站的使用人数锐减面对网站一堆问题陈xx也决定要将网站再次大幅度调整将之前的网页程序以及 SQL 查询语句全部重写他们花了三个月的时间执行 陈xx还在原本的网页服务器与数据库服务器的架构中加入一组应用程序服务器作为网页服务器 cache 数据的来源 改版之后的新网站搜寻速度提升许多先前每日的统计数据中处理速度超过 秒的数据超过 万笔而改版后每星期超过 秒的查询不到 笔而这少数反应速度不够快的查询也多是内部作业执行大量批处理导致的 由于原本使用的 L Switch 较为老旧负载量比较差因此陈xx选择将它汰换新的设备加强负载量恰好那时正好准备将应用服务器的架构上线就藉此机会将网络架构更新陈xx说这样的架构搭配负载较强的 L 交换器强化网站的处理性能并凭借此抵御网络攻击在此之后网站依然会受到零星攻击但都不会对造成太大影响 () 用硬件做快取或缓沖砸钱加装 AP Server 数字之墙 网站外销的个人实践 (二)运营 以下引用自原文: 全盛时期来自美国 blog 的流量每天达 万次这个数字其实不高对程序高手来说是小菜一碟但笔者是半吊子工程师知识有限也因此可能程序写得不好频频被主机供货商发信警告要求改善网站系统性能最后我决定开发 cache system cache system 缓存系统上线后将数据库读写从每天 万次降低到每天 万次这期间也请高手朋友帮忙进行数据库结构优化帮助很大笔者在过程中学习到一个良好的「缓存系统 (cache system)」对于提供 Widget 功能的网站来说非常重要 …中间略… 能够做到随时搬迁整个网站到另一家主机供货商除了程序本身的调整外还要归功于网站管理软件的盛行在此要推荐的一套称为 Plesk 的网站管理软件有的主机供货商会直接帮你安装 Plesk 免费或另外付费 Plesk 的所有管理功能都是透过 Web 界面方便到无以复加大大降低对技术能力的要求 除了 Plesk 以外网站管理软件还有其它选择还有 WHM 加上 cPanel 的组合也是常见的网站管理解决方案不过笔者还是比较偏好使用 Plesk毕竟使用起来容易也难怪他们的市场占有率一直是独大只是功力高的工程师可能会喜欢 WHM + cPanel因为弹性比较大不论选择哪一种都可以帮助你节省许多时间 () 加装实体机器做 Loading Balance (负载平衡)一些 Server OS 亦内建此类设定功能 () 程序技巧 ADONET 能用 DataReader 就不要用 DataSet / DataTable前者读取速度快又不耗内存后者虽较有弹性但速度较慢又会每个使用者消耗许多内存若您连 DropDownList 控件的数据来源都用 SqlDataSource 控件的默认值 DataSet则当页面里塞了一堆下拉选单时性能当然会受影响 但前提是程序员对 ADONET 要有一定程度的了解若只会用 Visual Studio 透过图形界面拖拉 TableAdapterDataTablexsd 就免谈了 若为 DataTable 建立 Primary KeyDataTable 会建立一个索引追蹤新增到 DataTable 中的数据是否符合此条件约束 (constraint)ADONET 会使用 algorithm 的「红黑树算法 (RedBlack Tree是一种「平衡树」算法) 去处理索引让 DataTable 的数据量大时较方便维护索引但缺点是建立索引时会降低一些性能 此外数据库的访问和捞值应该尽量在一次 DB connection 做完一个 connection 可搭配多个 DbCommand 对象使用不用每次都一个 DbConnection 配一个 DbCommand 在此推荐一本不错的 ADONET 原文书: Programming Microsoft ADONET Core Reference: Microsoft%C%AEADONETCoreReference/dp/X/ref=sr__?ie=UTF&s=books&qid=&sr= 有探讨许多市面上书籍少见的深入内容像 Oracle + ADONET 的各种应用Connection Pooling 的特性各种的数据库 Balk (批次) 作业应用 () 程序技巧 NET 语法 * 避免一些书上教的把 DataTable 或大量数据直接塞进 Session 里此举在真正要上线的系统必死无疑Session 在多人同时上线时内存的消耗是很可观的因为 Session 是每个用户各存一份在服务器的内存里而非像「缓存 (cache)」是所有的用户共享服务器的一块内存在很多 ASPNET 的需求中可用 HiddenField 控件或 ViewState 取代 Session * 能用「泛型 (Generics)」就不要用旧版的写法Generics 除了安全外亦可避免 NET 类型在 Boxing / Unboxing 转型时影响性能例如: 能用 List<string> 就不要用旧的 ArrayList能用 Dictionary<TKeyTValue> 就不要用 Hashtable 或跑双层的循环 (loop)因 ArrayListHashtable 的 element 属于 object 类在存储或检索如 int 等「值类型 (Value Type)」时会引发 Boxing / Unboxing 在大多数的情况下ListDictionary 等泛型类拥有较佳的效率而且是类型安全的 当然上述前提是系统要用 NET 开发还在靠 ASP 或非 OOP 语言硬撑的旧系统就免谈了 () 程序技巧 数据库「事务 (Transaction)」 您是否知道 SQL Server 的默认「事务隔离等级 (Isolation Level)」是「ReadCommitted」当您在写 ADONET 用了 SqlTransaction 时默认是当某个人在修改某一笔记录时其它所有读取这一笔记录的人都会被「锁定 (lock)」住造成其它全部用户的浏览器都在等待中无法做其它工作 而 Oracle 事务的特性是绝不会有类似无法读取的情形至少会用类似 SQL Server 新增的「快照隔离 (Snapshot Isolation)」让用户至少能先读取到未 Commit 或 Rollback 的记录而不用呆坐在浏览器前面傻等 不过 SQL Server 的「快照隔离」默认未启用用 SQL Server 开发的系统若怕用户被锁定的问题可视 project 需求改用最宽松的「ReadUncommitted」事务隔离等级其特性为不会造成任何锁定但可能会造成 Dirty ReadSQL Server 有下列七种「事务隔离等级」有兴趣的网友可去查询 ADONET 书籍或 MSDN Library: Chaos ReadCommitted// SQL Server 默认值 ReadUncommitted// 最宽松会有 Dirty Read RepeatableRead Serializable// 最严会有大量的锁定 Snapshot Unspecified () ASPNET 分页 GridView + SqlDataSource 的默认行为就是每次换页或排序时不管数据库有几笔记录都全部重捞一次当数据库有一百万笔数据就在每个用户换页时都一百万笔全部重捞出来此举消耗了大量的 Web server/ AP server 内存数据库系统资源网络频宽结果网站性能可想而知 很多企业内的小型网站为了省钱随便外包给低价抢标的工作室或没经验的学生和 SOHO 族可能因此埋下了恐怖的后遗症最可怕的是这些未爆弹在开发期间和系统刚上线数据量还很少时都感觉不出来有如癌症一样会在将来忽然爆发 () ASPNET AJAX 的 UpdatePanel 控件不是万能的 以下引用自 MSDN Magazine: 不论好坏UpdatePanel 控件都是 ASPNET AJAX 社区所喜爱的我说好是因为 UpdatePanel 使部分页面呈现变得相当简单而说坏是因为它的简便和易用性是以效率和令人啼笑皆非的带宽为代价的 UpdatePanel 可以为一般的网页带来 AJAX 神奇的好处但是它不能提供我们与 AJAX 正常关联的高效性例如您是否知道当 UpdatePanel 控件对服务器执行异步 AJAX 回调以更新其内容时这个请求包含了常规 ASPNET 回发所包含的一切其中还包括 ViewState 呢?具有太多 ViewState 的页面会降低性能并且具有太多 ViewState 的页面在 ASPNET 应用程序中都太常见 如果您准备使用 UpdatePanel 控件您需要清楚您在准备干什么在许多情况下从性能的角度而言应用程序最好是不使用 UpdatePanel而是使用对 WebMethods 或页面方法的异步调用 …中间略… 当您使用 UpdatePanel 在一个页面上执行无闪烁更新时您可能会认为您在进行高效构建毕竟UpdatePanel 使用的是 AJAX不是吗?不幸的是如果您在 UpdatePanel 更新时检验一下网络中的通信您会发现您根本就没有保存什么东西至少是在发送的时候没有保存通常在回发期间传送到服务器的 ViewState 数据(与其他数据)也会在 UpdatePanel 回调期间传送事实上来自 UpdatePanel 的异步 XMLHTTP 请求中所增长的数据几乎与在标准 ASP NET 回发中增长的数据相同下面是有关 ASPNET AJAX 不可告人的秘密UpdatePanel 虽易于使用但是通信效率不高 几乎没有什么办法可让您提高 UpdatePanel 的效率但是您可以放弃使用 UpdatePanel并转而使用 ASPNET AJAX 的其他功能来更新页面内容它不仅同样流畅而且更加高效它只需要多一点点力气但是最后的结果往往让人觉得是值得付出的因为您可以大大降低在客户端与服务器之间传输的数据量 () Design Patterns 虽然「设计模式」不是为解决性能问题而诞生的但可适度防止没经验的新人做出蠢事多学一些 NET 技术敌营注重的系统架构OOADDesign Patterns 和相关的 Framework对提升自己的身价和薪资也有帮助 |