QQ群请加: 6539042(powerbuilder11&SQL)
数据库可以承受很高的查询频率,但是对一个表过于频繁的查询,或者索引建立的不好,使得查询和占用过程太久,非常容易锁表,另外一些严重的是:对表统计,按没有索引的字段查询,分组汇总,对字段作函数(function(col_name))而造成不走索引,或者索引无法覆盖条件,或者对一个表作大量删除,插入,造成索引更新。如此种种,对客户端数量众多的使用系统,最直接的结果就是锁表,或者返回慢。服务器端反映就是慢,或者CPU,RAM占用满。一些OA,工单运用将刷新时间设置的太短,客户端少时,问题不明显,客户端多的时候,整个系统反映迟钝。甚至锁死。
我整理了一些想法。但自己并不专业,有错误肯提。
1. 本地需要的一些常用资源,必须在启动时,或者第一次用到时检索到本地,直到关闭客户端时,就只会检索服务器一次。比如部门,或者一些下拉选择项,这些开帐后不容易变动,如果某客户端申请增加了一个选项,比如"收费项目",提醒她退出一次即可。
2. 不容易变动的,而且是频繁使用的应该先到本地来。在本地有两个数据表,需要一个数据时,比如单据时间,要看本地有没有,没有再写内嵌式SQL去查询,不要动不动就是内嵌式SQL。
3. 避免在本地构建复杂的SQL语句,复杂SQL考虑在存储器里作。因为简单select语句构建的过程执行无法分步进行(或者语句看起来零乱无序),整个返回之前,可能需要锁住的资源比较多。用procedure主要是代码经过编译和优化,而一般的查询语句,如果比较复杂,我们的经验知道返回都很慢,而你重复的查询一次,就比较快了。如果100个客户端都要这么一个过程的话,对服务器是个拖累。而且层次不清和维护很难。更新也没存储器方便。
4. 在存储器中。如果对一张用户使用很频繁的表(主要信息表)作汇总,或者大面积返回时,会有困难。为了避免这个问题,存储器要把需要的字段提前检索出来,到一个临时表里,再操作,不会干扰到其他人的使用。因为有的人会用分类汇总,排序,以及用没有索引的字段参与筛选,或者对字段作函数运算,都是非常耗时的。有的要使用光标fetch。另外要重复使用一个数据时,比如根据字段:status来作一些不同的统计,要先检索到一个变量里,避免频繁的无谓的重复查表。
5. 在master-detail的表现形式时,有的用户会在master表频繁的点击。注意用户如果点击时没换行,不需要重新检索。我之前很好笑,一直没注意到这个问题。查询的频率会高十倍以上。(好笑)
6. 有时我们的程序在tab_control或者跌层或者展示部分隐藏时,用户实际上看不到隐藏的部分,所以也不需要刷新数据。节省这些地方能省下很多检索。
7. 自动刷新的界面要概算一个适合的时间间歇。如果一个系统10个人,10秒刷一下都没问题。但是一个系统50,100个人在用,刷新实际上是灾难的。对一些FK表到没问题,对有人频繁写入数据的表就不行。比如要统计每个部门新的工单数量,可以定时由存储器统一把结果刷到一个另外的表里,然后其他人从另外的那个表里读取,不需要每个人都来调用刷新的SQL语句来作分组count或者sum。比如服务器作就是一分钟时间一次,而客户端来作就是一分钟100次。
8. 开启一个测试客户端,仔细跟踪提交的语句,逐渐优化和分析。减少不必要的查询。
9. 三层结构因为会话独立,所以并不能改善以上问题。因为只是商业逻辑得到集中存放和调用。本身的检索还是要注意优化。比如上面说的部门代号表,虽然通过三层去读取,但也要一次都到本地来。而不是反复读。
10. 不要试图构建复杂的触发器。是个大忌。
11. 客户端数据返回行数的限制,默认的情况下,你可以限制为select top 100 * from table而界面可以给一个勾选项,如果客户要返回更多,去掉勾即可。我看一些web程序,每页只有20行,如果一些全局管理职位,她通常要一次导出所有的数据来,或者她看到范围比较大,几乎被系统累死掉。所以通常情况下,考虑一般操作人员作最优性限制,而对一些特殊用户,要放宽限制。
12. 列数和行数一样,返回太多速度很慢,只需要必要的栏位。但有时为了一个部件通用,而不会去节省一些列的返回也是可以的。
13. 查询时,不要自作多情的先给出一个list。我见过一个delphi程序员,他作的BOM表查询一进去界面就列出200行数据的一个列表,我觉得是不必要的。用户按条件查询就可以了。不外乎在条件组合灵活一些,或者缓存历史记录,或者给一些便捷的按钮即可。BOM表的物料那么多,即使你给一个列表,要在列表里查找也是个问题。这是个低概率问题。比如说故障工单处理,客户一进去倒可以刷新出最近50张,因为用户会察看这些单,是个高概率问题,这个是可以的。