SQLの「Hash Value」について

このQ&Aのポイント
  • Oracleの「Hash Value」とは、SQL文に固有に振られるIDであり、SQLの文字列をハッシュ計算によって生成される値です。この値は基本的には一意に定まりますが、稀に衝突が起こることもあります。
  • 「Hash Value」は再起動やインスタンスの異なる環境でも変化しない値です。ただし、大文字小文字やスペースの数、改行の位置が異なるだけでも異なる値として扱われるため、SQL文が微妙に変更された場合には異なる「Hash Value」が生成されます。
  • 「Hash Value」はSQLのパフォーマンスチューニングなどで使用される重要な情報であり、一意性と安定性が求められます。Oracleのアルゴリズムによって生成された「Hash Value」は、一般的には衝突が起こらないように設計されていますが、完全に衝突がないとは言い切れない場合もあります。
回答を見る
  • ベストアンサー

SQLの「Hash Value」について

oracleのStatspackレポートに出てくる9iまでの「Hash Value」もしくは10g以降の「Old Hash Value」について教えてください。 この値は「SQLに固有に振られるID」だと考えていたのですがこの認識はあっていますでしょうか? ※大文字小文字・スペースの数・改行の位置が異なるだけでも異なる値になり、別のSQLと判断されてしまうということは知っています。また、oracleのバージョンが異なっても同じアルゴリズムが使用されていることも知っています。 「Hash Value」という言葉から連想する私の想像の範囲に過ぎませんが ・SQLの文字列をhash計算により算出しているのだろう ・基本hash値だけで「ほぼ」一意に定まる ・稀に衝突も起こりうる ・実質的には変化する値であり、実は「ID」ではなく、一貫性は保障されない ではないかと思います。 なのですが、一意であると保障されなければ実用性が下がってしまうと思います。 例えば再起動したら変化してしまう可能性があるとかだと。 衝突は絶対にありえないのでしょうか? どんな状況でも変わることのない値なのでしょうか? 再起動しても、インスタンスが異なっても変わることはないのでしょうか? 稀に変化してしまう値なのでしょうか? この点について教えてください。よろしくお願いします。

  • Oracle
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • entree
  • ベストアンサー率55% (405/735)
回答No.1

SQL はSQL_ID とHASH_VALUE でユニークになっていたと思いますが。 HASH_VALUE だけでは衝突の可能性が全くないとは言えないことはご認識の 通りだと思います。 もっとも、そんな簡単に衝突するのであればSHA1やMD5などが役に立たないと いうことにも繋がってくるので、故意に衝突させることは不可能なレベルではありますが。

mibusys
質問者

お礼

「Hash Value」はそもそも「ID」では無いのですね。衝突可能性がある値であるということがわかりすっきりしました。それで別途「SQL ID」が用意されているのですね。 参考になりました。ありがとうございました。 個人作成のサイトなので情報の信頼性は十分ではありませんが、近い情報があったので、メモしておきます。 データベースコンサルタントのノウハウちょい見せ 私が使うSQL文の捕まえ方&実行計画取得方法 http://odakeiji.blog33.fc2.com/?mode=m&no=23

関連するQ&A

  • HASH(0x1801234) の意味は??

    hash のvalueに400文字程度の文字列(アルファベットのみで特殊文字なし)を入れて、呼び出そうとすると HASH(0x1801234) といった値が出力されるのですが、これはどういう意味でしょうか? hash の値に入れられる情報量には限界があるためにこのようになるのでしょうか。。 それとも違ったところに間違いがあるのでしょうか(念のため、エラーがでるperlスクリプトを下に書いておきます。長くてすいません)。 どなたかよろしくお願いいたします。 #! usr/bin/perl %hash_unique = (); $HSkey = 'a'; $HSval = 'SELCVGINGFGHGPMKLMYMHSKEGIQKGIKVTAINDPFIDLQYMVYMFKYDSTHGRYKGEVHMEDGKLIVDGDAGALYVVESTGVFLSIEKASAHIQGGAKRVVVSAPSPDAPFQCMKPAEIPWKYDPSSMTIVSNASCTTNCLAPLAKVIHDNFGIEEALMTTVHAYTATQKTVDGPSAKAWRDGRGAHQNIIPASTGAAKAVGKVIPELNGKLTGMAFRVPVADVSVVDLLGYTEDSVMFVMGVNQDGQAISVVSSDFVGDTHSSIFDAGAGISLNDNFVKLISRIGRLVLRACLTCRLTRPASYANIKESVKKAAWYDNEFGYSHRVADL'; $hash_unique{"$HSkey"} = {"$HSval"}; print $hash_unique{"$HSkey"};

    • ベストアンサー
    • Perl
  • 一意(ユニーク)かつ、ソートに対してランダムなIDの発行方法

    随時増加するあるデータに対して、一意なIDを割り当ててゆきます。 通常は、1, 2, 3, … と連番を割り当てて行けば一意なIDになると思います。 その上で、IDでソートした時に発行順に並ぶのではなく、順番がランダムになるようにしたいのです。 (アルゴリズムを知らない人から、発行順を推測されないようにしたい。) そこで考えたのが、"1", "2", "3", …という文字列に対するハッシュ(SHA1やMD5)ですが、sha1("1"), sha1("2"), sha1("3"), …とIDを発行していった場合、IDが重複してしまう可能性を心配しています。(とても低い確率ではあることは分かっていますが、皆無ではありません。) ハッシュ関数を利用する他に、「一意」で「ランダム」で「衝突の可能性がゼロ」である文字列の生成方法はありませんでしょうか?(可能性がゼロというのは物理的に不可能だと思うので、例えばSHA-1であれば、160bitのハッシュが生成されますが、2^160個のIDを発行しても重複しない、ということを考えます。) 一応、規模は1000万ID程度を考えていますが、もっと大きなオーダーでも衝突しないに越したことはありません。

  • OracleのSQLについて

    OracleのSQLについて質問があります。 VARCHAR2をReturnするFunction「GETKANANAME(引数はID)」があるとします。 このとき Update NAMELIST SET kananame = (select GETKANANAME('00001') from dual); とすると、kananameに何も設定されません。 (エラーメッセージなどは何も出ていません。) select GETKANANAME('00001') from dual; だと期待する値が帰ってくるのですが…。 何か間違ったSQL文なのでしょうか?

  • 移植性のあるSQLの書き方

    現在Oracleを使用していますが、 将来他のDBに切り替える可能性もある、ということで、 移植性のあるSQLを書こうとしているのですが・・・ ある文字列フィールドの値がNULLか空文字列の場合、 という判定式で困っています。 普通のDBだと、   field IS NULL OR field <> '' と書くところですが、 Oracleの場合、空文字列=NULLなので、 上記の書き方をすると、field <> NULL という式が成り立たず、 常に偽になってしまいます。 移植性があり、且つ、パフォーマンス的にも問題のない、 なにかよい書き方ないでしょうか。。??

  • DELPHIでSQLテーブルをグリッドに読み込みしたい

    DELPHI6を使っております。素人です。 以下のようなプログラムを書きたいと思っております。 SQLテーブルに a_tbl というテーブルをつくり、 a_id varchar2 (一意) a_namae varchar2 a_kubun varchar2 という項目を作りました。 delphiでは、editboxを設置して、edit1という名前をつけました。 また、ボタン、グリッドを設置しました。 行いたい作業は以下です。 ・edit1に値を入力し、ボタンをクリックする ・「a_id」に格納されている値と、「edit1」に入力した文字とが一致するところの「a_namae」、「a_kubun」をグリッドに表示させる(編集はできない) どのようなプログラムにすればできますでしょうか?

  • SQL WHERE文のノットイコールについて

    初歩的な質問ですみません。 Oracle9iでsqlplusで接続しています。 「member_accountテーブルのdelete_flag(VARCHAR2)カラムの値が'1'ではない」ものを抽出したいと考えてます。 ただ、正しい結果が返ってきません。 何が問題でしょうか?よろしくお願いいたします。 ============================================================ SQL> select count(ID) from member_account; COUNT(ID) ---------- 16450 SQL> SQL> select count(ID) from member_account where delete_flag='1'; COUNT(ID) ---------- 107 SQL> SQL> select count(ID) from member_account where delete_flag<>'1'; COUNT(ID) ---------- 0 SQL> SQL> select count(ID) from member_account where delete_flag!='1'; COUNT(ID) ---------- 0 ============================================================ よろしくお願いいたします。

  • checkboxのvalue値を動的にしたい

    strutsタグのcheckboxのvalue値を動的に変更したいのですがうまく出来ません。 iterateでループし、チェックボックスが複数個(状況によって個数が変化する)できます。 このときvalue値を動的にして、submitしたときにどこのチェックボックスがチェックされたかを知りたい為に動的にしたいと考えています。 見当違いなやり方かもしれません。 どうぞ、ご教授下さい。宜しくお願いいたします <nest:iterate id="selectdata" name="selectAll" indexId="idx"> <tr> <td> <html:checkbox name="selectdata" property="checkBox" value=" ここの値を動的にしたい " /> </td> <td> <bean:write name="selectdata" property="user_id" /> </td> </tr> </nest:iterate> できればbean:writeのuser_idを入れることが出来るのならそれが一番良いのですが・・・ strutsタグのネストは出来ないのでしょうか?

    • ベストアンサー
    • Java
  • DELPHIでSQLテーブルを読み込み・編集・削除したい

    DELPHI6を使っております。素人です。 以下のようなプログラムを書きたいと思っておりますが、 参考書やネットで調べても以下の作業ができません。 SQLテーブルに a_tbl というテーブルをつくり、 a_id varchar2 (一意) a_namae varchar2 a_kubun varchar2 という項目を作りました。 delphiでは、editboxを設置して、それぞれ edit1, edit2, edit3という名前をつけました。 また、ボタン1、2を設置しました。 行いたい作業は以下です。 ・edit1に値を入力し、ボタン1をクリックする ・「a_id」に格納されている値と、「edit1」に入力した文字とが一致するところの「a_namae」を「edit2」に、「a_kubun」を「edit3」に表示させる ・edit3に表示した文字を変えて、ボタンをクリックすると「a_kubun」が 上書きされる ・「a_id」に格納されている値と、「edit1」に入力した文字とが一致する ものがない場合、edit2と3に入力してボタン2をクリックすることで 新規に「a_tbl」にレコードが記入される 教えてください!

  • 秀丸でSQLを書く際に SQLの予約語だけ大文字

    秀丸でSQLを書く際に SQLの予約語だけを、大文字に変換するよい方法は? たとえば select * from table_1 where id=1 order by id desc; と書いて、マクロを起動すると SELECT * FROM talbe_1 WHERE id=1 ORDER BY id DESC; となるようにするよい方法はありませんか? また、予約語が「強調」されると尚良いです。

  • C#で異なる環境のテーブル名をSQL上で指定したい

    お世話になります。 SQLSERVERとOracle上で共通して持っているIDを基にOracleのテーブルに保持している データをSQLSEVERで取得したいと思っています。 (1)SQLSERVERのテーブルA ID NAME ------------------ 111 NULL 222 NULL 333 NULL (2)OracleのテーブルB ID NAME ------------------ 111 情報1 222 情報2 333 情報3 444 情報4 (1)に存在しているIDでそのIDに紐づくNAMEを(2)より取得したいと思ってます。…(3) (3)SQLSERVERのテーブルC ※(1)とインスタンス・データベース名は同じ ID NAME ------------------ 111 情報1 222 情報2 333 情報3 上記の処理をC#で実現しようとした時に --------------------------------------------------------------------------------- // 接続文字列を生成する string stConnectionString = string.Empty; stConnectionString += "Data Source = local;"; stConnectionString += "Initial Catalog = master;"; stConnectionString += "Integrated Security = SSPI;"; stConnectionString += "MultipleActiveResultSets=true"; // SqlConnection の新しいインスタンスを生成する (接続文字列を指定) System.Data.SqlClient.SqlConnection cSqlConnection = ( new System.Data.SqlClient.SqlConnection(stConnectionString) ); // データベース接続を開く cSqlConnection.Open(); // cSqlConnection から SqlCommand のインスタンスを生成する System.Data.SqlClient.SqlCommand hCommand = cSqlConnection.CreateCommand(); System.Data.SqlClient.SqlCommand aCommand = cSqlConnection.CreateCommand(); // 実行する SQL コマンドを設定する hCommand.CommandText = "SELECT ID FROM テーブルA "; // 指定した SQL コマンドを実行して SqlDataReader を構築する System.Data.SqlClient.SqlDataReader hReader = hCommand.ExecuteReader(); // hCommand を破棄する (正しくは オブジェクトの破棄を保証する を参照) hCommand.Dispose(); while (hReader.Read()) { aCommand.CommandText = "insert into テーブルC select * from テーブルB where id = " + "'" + hReader["ID"].ToString() + "'"; int iResult = aCommand.ExecuteNonQuery(); MessageBox.Show(iResult + "行返しました"); } //aCommandを破棄する。 aCommand.Dispose(); //hReaderを閉じる hReader.Close(); cSqlConnection.Close(); cSqlConnection.Dispose(); --------------------------------------------------------------------------------- で実現したいと思っていますが、INSERT INTO ~SELECT文で指定しているテーブルBはOracle上にあるため、以下のようにOarcleへのコネクションを張る必要があると考えています。 //Oracleの接続情報(Oracle.DataAccess.dll・using Oracle.DataAccess.Client;を事前に追加) OracleConnection conn = new OracleConnection(); conn.ConnectionString = "User Id=scott;Password=tiger;Data Source=orcl;"; OracleCommand cmd = conn.CreateCommand(); conn.Open(); ~ ここで質問ですが、上記のOracleへのコネクションを張った場合、 C#内で指定しているテーブルBをどのように記述すれば(3)の処理結果を実現できるでしょうか? ご教授よろしくお願い致します。