[Oracle] V$SQLにおかしな数値が現れる!? | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

SQLのパフォーマンスチューニングをするときには、よく動的パフォーマンスビューV$SQLを検索して処理に時間のかかっているSQLを洗い出します。


処理時間はこのV$SQLのELAPSED_TIMEという列を見ればわかるのですが、時々ここにとんでもない値が出てくることがあります。


そのとんでもない値というのは何故かパターンが決まっています。


'184467440'で始まる20桁の数値なのです。


例えば、'18446744067030698118'など...


どうもバグっぽいんだが、ちょっと暇なときに調べてみました。

とりあえず'184467440'でググってみると、こんなサイト にたどり着きました。

これによると、どうも何かの拍子にオーバーフローを起こしておかしくなって、頭に16進数で'FFFFFFF'がくっついてしまうようです。

先ほどの'18446744067030698118'を16進数に変換してみると、

SQL> SELECT TO_CHAR( 18446744067030698118, 'fm000000000000000X' ) FROM DUAL;

TO_CHAR(18446744067030698118,'FM00
----------------------------------
FFFFFFFE71E8C886

なるほど...確かに先頭7桁が'FFFFFFF'になっています。

で、これを解決しようと思ったら、以下のように16進数に変換した後、先頭の'FFFFFFF'を取り除いてまた10進数に戻してやればいいというようなことをこのサイトには書いてありました。

上記の例で先頭7桁の'FFFFFF'を取り除くと以下のようになります。

SQL> COL A FORM 99999999999999999999
SQL> SELECT TO_NUMBER( SUBSTR( TO_CHAR( 18446744067030698118, 'fm000000000000000X' ), 8 )
, 'XXXXXXXXX' ) A FROM DUAL;

                    A
---------------------
          62040623238
一応もっともらしい数字は出てきます。

ただ、上記の例の場合、先頭7桁が'FFFFFFF'となっているのに対し、このサイトの例では、先頭8桁が'FFFFFFFF'となっており、

SQL> SELECT TO_CHAR( 18446744069546030898, 'fm000000000000000X' ) FROM DUAL;

TO_CHAR(18446744069546030898,'FM00
----------------------------------
FFFFFFFF07D5B732
その先頭8桁の'FFFFFFFF'を取り除いていました。
SQL> COL A FORM 99999999999999999999
SQL> SELECT TO_NUMBER( SUBSTR( TO_CHAR( 18446744069546030898, 'fm000000000000000X' ), 9 )
  2  , 'XXXXXXXXX' ) A FROM DUAL;

                    A
---------------------
            131446578
だから、単純に先頭の'F'を全部取り除くのが正解かどうかは怪しいところです。

とりあえずバグであることは間違いなさそうですが、解決策はびみょー^^;