要使用硬编码而不是使用宿主变量,如果程序员在SQL语句中使用了宿主变量字段,这一点就尤其重要。大多数COBOL程序都写为静态SQL程序而不是动态SQL程序。对于这些COBOL程序,执行DB2 Bind时,直至运行时之前优化工具都无法知道宿主变量中的具体值。所以,优化工具为SQL语句选择访问路径时,它会有一些默认的判定规则。
例如,假设一个表包含100万行。在这个表中,列Status_Cd上有一个索引。对这个表执行典型的Runstats时,优化工具会知道状态码(Status_Cd)有3个不同的值。运行一次特殊的Runstats之后,会为这个列指定频率值统计信息,DB2就会了解到以下数据分布:
状态码值A包含50%的数据。
状态码值B包含45%的数据。
状态码值C包含5%的数据。
COBOL程序包含以下SQL语句,其中程序中设置的值总是C:
- SELECT COL1, COL2, COL3
- FROM TABLE
- WHERE STATUS_CD = :WS-STATUS_CD
如果使用宿主变量,绑定时优化工具要确定一个访问路径,此时它并不知道要处理什么值,不过它知道在这100万行中有3个不同的状态码值。其默认规则就是不论运行时是什么值,都大致访问1/3的数据。考虑到要访问1/3的数据,很多情况下它会选择对数据完成表空间扫描。
如果COBOL程序包含以下SQL语句:
- SELECT COL1, COL2, COL3
- FROM TABLE
- WHERE STATUS_CD = 'C'
通过硬编码写入‘C’,优化工具可以进一步浏览系统编目表,查看到只有5%的数据的STATUS_CODE列值为C,由于这个原因,选择访问路径时它可能会选择使用索引。
代码中要尽量使用硬编码值,这并不是一个标准,甚至不能算是SQL的编码实践原则。不过,很多情况下,通过使用硬编码值可以显著改变所选择的访问路径,从而使性能大为改善。如果某些列值的数据分布很不均匀,这种做法就尤其适用。要记住,通常需要运行一个特殊的Runstats来得到额外的分布统计信息。这些信息称为频率值统计信息。如果不能在程序中写入硬编码值,可以考虑使用REOPT绑定参数,它会在运行时使用宿主变量中的值对查询执行一次“再优化”。不过,要当心REOPT,因为它会在程序执行时对每一个SQL语句进行再优化,这可能会增加执行时间,以至于抵消基于值再优化所节省的时间。