[轉] sql_id VS hash_value
有沒有發現,v$session,v$sql,v$sqlarea,v$sqltext,v$sql_shared_cursor等試圖連接的時候經常會用到hash_value,sql_id,但是他們2個之間到底有什么不可告人的關系呢?
Talnel以及評論的一坨人(包括jonathan)給了一個蠻不錯的解釋:
SQL_ID is just a fancy representation of hash value
sys@TESTDB>select kglnahsv, kglnahsh from x$kglob where kglnaobj ='select ''landrover'' from dual'; KGLNAHSV KGLNAHSH --------------------------------- ---------- 8605074c682c4c4da7d495aacf3751e2 3476509154 8605074c682c4c4da7d495aacf3751e2 3476509154 sys@TESTDB>select sql_id, hash_value, old_hash_value from v$sql where sql_text ='select ''landrover'' from dual'; SQL_ID HASH_VALUE OLD_HASH_VALUE ------------- ---------- -------------- agp4ppb7mfng2 3476509154 3053997704
同時,10g+提供了一個sql_id到hash_value轉換的方法:
sys@TESTDB>select dbms_utility.SQLID_TO_SQLHASH('agp4ppb7mfng2') hash_value FROM DUAL;
HASH_VALUE
----------
3476509154
10g以后,他們的關系是這樣的:
1)oracle 用MD5算法對library cache obj 進行哈希,生成一個128bit的hash value,也就是KGLNAHSV(16進制).
2)KGLNAHSV的低64bit作為SQL_ID(32進制).
3)KGLNAHSV的低32bit作為HASH_VALUE(10進制)
因為10g+的哈希算法變了,所以10g之前的hash_value其實v$sql.old_hash_value。
但是需要說的是,library cache obj實際上還是通過hash_value+address的方式來組織的,Tanel只說了sql_id的后4 bytes是hash_value,但是沒有說前4 bytes代表什么含義,個人覺得KGLNAHSV中有一部分應該是代表了address的,因為既然hash_value是sql_id的子集,如果sql_id可以唯一確定一個obj,那單獨用hash_value肯定會存在不同SQL_ID但HASH_VALUE沖突的情況,盡管目前沒人遇到過或者證明過,以他得話來說,可能性是1 in 4 billion。
至于oracle推出SQL_ID的意義,Tanel認為只是hash_value的一個更友好的別名。按照jonathan的說法,以后的版本可能會逐漸淘汰4 bytes的HASH_VALUE,而改用8 bytes的SQL_ID(也許名字會不一樣),因為他更精確。但是現有的代碼很多地方都還使用的32-bit的hash_value,所以hash_value需要做到向后兼容,就像當初10g逐漸淘汰9i的哈希算法一樣(v$sql.old_hash_value)。這可能就是sql_id的意義所在。
具體計算可以參考:
關于sql_id與hash_value
Oracle sql_id and hash value
浙公網安備 33010602011771號