你交待清楚了吗? 荣耀 2002冬 我曾写过一个通用查询程序(下文称之为XQuery),这个程序可以按照用户的意思,将输入的SQL语句的查询结果以棒图、曲线等形式显示出来。 XQuery一直工作得很好,直到有一天一位工程人员发现,同样的一条SQL语句,当查询某些节点下的数据时,速度很快,而当查询某个节点下的数据时,慢得要命。这个节点下的数据并不多,也就是几百条记录的样子。 我将这条慢的SQL语句(满足这个节点条件的SQL语句实体)在命令行工具里执行了一遍,速度非常快,这说明SQL语句本身不存在什么效率上的问题(后来证明我错了)。 于是,疑点被转移到了程序上,但经过仔细跟踪调试,这种可能性很快也被排除。 我曾碰到ODBC这样的数据访问层的bug,也不止一次发现过开发环境的bug,但这一次不象是这两种情况。 问题显然和数据有关。我到数据库里大略看了一下,并没有发现满足这种条件的数据有什么特别之处。 项目马上就要验收,问题必须解决,客户很着急,我陷入了困境。 思虑再三,我又打开了这条SQL语句涉及的几个表,仔细查看一番。有一个表中用于保存图片的BLOB字段引起了我的怀疑。我细心检查了一下这些BLOB字段中的数据,发现有的有图片,而有的则为空。 进一步查实后发现,使用我的查询工具,导致执行查询速度缓慢的,正是那些有图片的数据。原来一位客户正在往记录里补充图片,也只有这个节点下的数据被存入了照片。 使用命令行工具执行这条有问题的SQL语句速度之所以很快,原因在于命令行工具本身就无法显示图片型的字段,在执行查询时,BLOB字段被自动忽略(优化)掉了。 而使用XQuery时,由于用户没有设置这个字段的显示方式为图片,默认来说,什么都不显示,所以就没有引起我的注意,但实际上执行查询时,已经将图片数据取到了客户机器内存之中。补充说明一下,这些图片都很大,每个都有1M多(唔,几百条记录呢)。 但用户的确也需要查看图片,这又怎么办? 于是,我就利用XQuery提供的主—子查询功能,定义了一个一对一的主子查询(唔,这本来是为一对多主子查询而设计的),先将用户要查询的主要参数提取出来,当他具体关心某条记录的图片时,选中该记录,才会到数据库里检索相应的图片。这就既解决了速度问题,又满足了用户需求,皆大欢喜。 这不属于“防御编程”的问题,程序没有崩溃,只是效率下降,而这是程序本身无论如何都无法避免的,只要用户喜欢,他就可以定义任何SQL语句,比方说,即使不查询这些图片,他同样可能会有意识地写出一条一次可检索出几十万乃至几百万条记录的SQL语句来。 根据用户是否设置字段的显示方式为图片(或其他格式)来优化SQL语句看上去是个好主意,实际上并非如此。程序的表示层和业务规则层是分离的。尽管业务规则层可以要求表示层程序采用某种消息机制来通知其是否(和如何)优化正被执行的SQL语句,但它无法强制表示层那么做,表示层程序可能会忘记通知业务规则层。 所以,当我们向用户宣扬软件的功能和优点的时候,请不要忘了向用户交待清楚,软件中也存在陷阱,并告诉她规避的方法。 -完- |