因为一大早有个合作伙伴前来交流,所以昨天的文章实际上是匆匆发出来的,并没有完整的表达出我对这个问题的看法。今天在外面出差,本来和客户约好上午见面,因为临时的安排问题,又改到下午了,所以早上有比较充裕的时间来写一写昨天想表达的另外一层意思。
表连接的性能关系到绝大多数管理信息系统的性能问题,而最常用的表连接方式就是NESTED LOOP和HASH JOIN。当HASH JOIN还不成熟的时候,NESTED LOOP是主打,不过对于一些左表返回数据较多或者说找不到一张返回数据量较少(比如小于几百)的左表的情况下,SQL的性能是很差的。HASH JOIN让一些大查询的性能得到了有效的优化。不过HASH JOIN也不是任何时候都有效的,如果原本使用NESTED LOOP的连接被错误的选择为HASH JOIN,会带来巨大的不必要的扫描开销,也会影响SQL的执行时间。因此选择适当的表连接方式对于SQL性能来说十分关键。
昨天在我的测试中存在问题的执行计划,实际上都是企业的信息系统中很常见的SQL产生的,这些SQL在Oracle中表现都是很好的,而当使用某些开源数据库或者国产数据库时才会出现问题,这也反映出我们的国产数据库在优化器上与Oracle的差距。优化常见表连接的执行计划的能力,实际上应该作为国产数据库十分重要的一项工作来做。
SQL解析过程中都会有SQL REWRITE这个阶段,实际上我们遇到的很多SQL的执行计划有问题,都是在这个阶段没能改写出更优的SQL来,所以后续的执行计划生成就会陷入到优化器的缺陷中了。优化器的改进是个十分艰苦的过程,其难度巨大,PG数据库这些年虽然版本迭代很快,但是优化器中的几个顽疾一直没有解决掉(昨天我举的例子中的执行计划存在问题的地方,都是PG优化器由来已久的顽疾),这也充分说明了优化器核心提升的难度。
不过SQL REWRITE这个阶段与优化器的核心之间相对独立(当然其中关联也十分紧密),因此优化SQL REWRITE阶段的能力可以作为数据库厂商优先发力的地方,能够把一个优化器较难处理的SQL改写出一个比较容易处理的SQL,那么某些老大难的问题就不需要动优化器的核心,也能够解决问题了。
一年期我写过一篇文章《从两个小例子看我们的差距》,其中一个是我们以前讨论过的一个ORACLE CBO优化器的例子。在一份100053 trace里,我看到了一个十分奇怪的现象,SQL语句被莫名其妙的做了一次谓词内推(FPD)的转换,在SQL上莫名其妙的增加了一个基于函数索引的谓词断语。刚开始的时候,我认为这种SQL REWRITE后,甚至语义都变了,SQL的执行结果都有可能不对了,Oracle CBO为什么要做这样的FPD呢。后来经过分析发现SQL有个WHERE ADATE=’20210102 122103’ 这样的条件,不过ADATE上并无索引,不过存在一个substr(ADATE,1,8)索引。按理说这个索引不会被使用,不过这个场景下,使用函数索引能够有效地提高SQL的效率。而在Oracle的核心优化器中增加这方面的能力将会是一个大改动,于是Oracle巧妙的添加了一条FPD规则,对此类SQL通过规则进行一次简单的改写,优化器对于处理此类Sql的性能就大大提高了。
最近这一年里,做了大量的数据库国产化替代相关研究与测试工作,我发现现在绝大多数国产数据库都在高唱秒杀一切的性能,优秀的TPC-C/TPC-H指标,不过我们的用户的实际体验是应用从Oracle迁移下来以后大量的SQL执行性能下降数十倍甚至数百倍。基于这些应用体验,我觉得我们的国产数据库厂商真的需要在这些“小地方”多下点功夫,能够让用户用得更爽。因为我们用户的应用场景中,超过99%的场景是普通的管理信息系统,而不是超高并发,超高交易量的TPMC场景。能够踏踏实实把用户最需要的日常问题都解决好了,用户的应用开发,应用迁移成本都降低了,自然使用你的产品的用户就会越来越多。