战略优先于战术
Strategy Before Tactics
战略决定战术,反之则谬也。思考如何处理数据时,有经验的开发者不会着眼于细微步骤,而是着眼于最终结果。要获得想要的结果,最显而易见的方法是按照业务规则规定的顺序按部就班地处理,但这不是最有效的方法——接下来的例子将显示,刻意关注业务处理流程可能会使我们错失最有效的解决方案。
几年前,有人给了我一个存储过程,让我“尝试”着进行一下优化。为什么说是“尝试”呢?因为该存储过程已经被优化两次了,一次是由原开发者,另一次是由一个自称Oracle 专家的人。但尽管如此,这个存储过程的执行仍会花上20分钟,使用者无法接受。
此存储过程的目的,是根据现有库存和各地订单,计算出总厂需要订购的原料数量。大体上,它就是把不同数据源的几个相同的表聚合(aggregate)到一个主表(master table)
中。首先,将每个数据源的数据插入主表;接着,对主表中的各项数据进行合计并更新;最后,将与合计结果无关的数据从表中删除。针对每个数据源,重复执行上述步骤。所有 SQL 语句都不是特别复杂,也没有哪个单独的SQL语句特别低效。
为了理解这个存储过程,我花了大半天时间,终于发现了问题:为什么该过程要用这么多步骤呢?在from子句中加上包含 union 的子查询,就能得到所有数据源的聚合(aggregation)。一条select 语句,只需一步就得到了结果集,而之前要通过插入目标表(target table)得到结果集。优化后,性能的提升非常惊人——从 20 分钟减至 20 秒;当然,之后我花了一些时间验证了结果集,与未优化前完全相同。
想要获得上述的大幅提高性能,无需特别技能,仅要求站在局外思考(think outside the box)的能力。之前两次优化因“太关注问题本身”而收到了干扰。我们需要大胆的思维,站得远一些,试着从大局的角度看待问题。要问自己一些关键的问题:写存储过程之前,我们已有哪些数据?我们希望存储过程返回什么结果?再辅以大胆的思维,思考这些问题的答案,就能得到一个性能大幅提升的处理方式了。
总结:考虑解决方案的细节之前,先站得远一些,把握大局。






