So, despite only SQL_ID showing up everywhere in Enterprise Manager and newest Oracle views and scripts, the hash_value isn’t going anywhere, it’s a fundamental building block of the library cache hash table.“
即尽管10g以后通常使用SQL_ID代表一条SQL,但实际上库缓存物理上还是使用HASH_VALUE组织的。使用SQL_ID查询X$KGLOB或V$SQL视图时,Oracle也是仅仅抽取出SQL_ID的低4个字节,仍旧通过HASH_VALUE值进行检索的。
因此,尽管在EM以及Oracle视图和脚本中到处可见SQL_ID,但实际HASH_VALUE仍起着作用,它才是构建库缓存哈希表的基础。
他也给出了一个用于SQL_ID和HASH_VALUE转换的脚本,用的就是如下SQL:
select
lower(trim('&1')) sql_id
, trunc(mod(sum((instr('0123456789abcdfghjkmnpqrstuvwxyz',substr(lower(trim('&1')),level,1))-1)
*power(32,length(trim('&1'))-level)),power(2,32))) hash_value
from
dual
connect by
level <= length(trim('&1'))
/ 现在我们就能知道instr中这一串的字符是什么意思了,其实就是base-32转码的可见字符。也就能说明文章开始的两条SQL为什么看似相同,但结果不同了,其实就是base-32转码使用的不对。
总结:
凡事都有因果,开始碰到这么一条SQL时,想当然认为就是0-9,a-z连续的字符,但其实这里用到的是base-32转码,并不是连续的字符,因此理解其背后的原理,才有助于清楚这里为什么这么用,而不是那么用。