sql >> データベース >  >> RDS >> Oracle

ORA_HASH関数で使用されるアルゴリズムは何ですか?

    「使用しているように見える」場合は、リバースエンジニアリングを少し行って、正確に何が呼び出されているかを確認し、関数のコードを逆アセンブルするのが理にかなっています。

    ただし、Oracleの内部に飛び込みたい場合は、次のことが役立つ場合があります。

    まず、内部C関数がどのように呼び出されるかを理解する必要があります。これを行うには、1つのセッションで長時間実行されるコードを実行できます。これを実行しました

    select avg(ora_hash(rownum)) id from
    (select rownum from dual connect by rownum <= 1e4),
    (select rownum from dual connect by rownum <= 1e4);
    

    PL/SQLコードでもかまいません。常にora_hashを呼び出すようにする必要があります。

    実行中

    Windowsでテストしたところ、ora_hashは...-> evaopn2()-> evahash()のようです。 -> ...

    それでは、evahashをグーグルで検索しましょう。公式サイト https://oss.oracle.com/projects/ocfs-tools/src/branches/new-dir-format/libocfs/Linux/inc/ocfshash.h > evahashへのリンク付き。

    そして最後に、実際のCコードhttp://burtleburtle.net/bob/hash/のページがあります。 evahash.html

    これまでのところ、ライブラリ(WindowsではDLL)に組み込むと、Oracleで外部C関数を使用できることを覚えています。

    たとえば、Winx64で関数のシグネチャを

    に変更した場合
    extern "C" ub4 hash( ub1 *k, ub4 length, ub4 initval)
    

    Oracleからは正常に実行できますが、ご覧のとおり、署名はOracleのora_hashとは少し異なります。この関数は、値、その長さ、および初期値(シードの場合があります)を受け入れますが、Oracleの署名はora_hash(expr、max_bucket、seed_value)です。

    Oracleをテストしてみましょう

    SQL> select ora_hash(utl_raw.cast_to_raw('0'), power(2, 32) - 1, 0) oh1,
      2         ora_hash('0', power(2, 32) - 1, 0) oh2,
      3         ora_hash(0, power(2, 32) - 1, 0) oh3,
      4         ora_hash(chr(0), power(2, 32) - 1, 0) oh4
      5    from dual;
    
           OH1        OH2        OH3        OH4
    ---------- ---------- ---------- ----------
    3517341953 3517341953 1475158189 4056412421
    

    C

    int main()
    {
        ub1 ta[] = {0};
        ub1* t = ta;
        cout << hash(t, 1, 0) << endl;
        ub1 ta0[] = {'0'};
        ub1* t0 = ta0;
        cout << hash(t0, 1, 0) << endl;
        return 0;
    }
    
    1843378377
    4052366646
    

    どの番号も一致しません。問題は何ですか?ora_hashは、ほとんどすべてのタイプのパラメーターを受け入れます(たとえば、select ora_hash(sys.odcinumberlist(1,2,3)) from dual )一方、C関数は値をバイトの配列として受け入れます。これは、関数呼び出しの前に何らかの変換が行われることを意味します。したがって、前述のCハッシュ関数を使用する前に、実際の値がどのように変換されてから渡されるかを理解する必要があります。

    IDA PRO +六角光線を使用してOracleバイナリのリバースエンジニアリングを進めることができますが、それには数日かかる場合があります。プラットフォーム固有の詳細は言うまでもありません。

    したがって、ora_hashを模倣する場合、最も簡単なオプションは、Oracle Express Editionをインストールし、それを使用してora_hashを呼び出すことです。

    それが面白かったと思います。頑張ってください。

    更新

    ora_hashとdbms_utility.get_hash_valueは相互にマッピングできます( https:/を参照) /jonathanlewis.wordpress.com/2009/11/21/ora_hash-function/

    SQL> select dbms_utility.get_hash_value('0', 0 + 1, 1e6 + 1) ha1,
      2         ora_hash('0', 1e6, 0) + 1 ha2
      3    from dual;
    
           HA1        HA2
    ---------- ----------
        338437     338437
    

    dbms_utilityのパッケージ本体をアンラップすると、次の宣言が表示されます

      function get_hash_value(name varchar2, base number, hash_size number)
        return number is
      begin
        return(icd_hash(name, base, hash_size));
      end;
    

    および

      function icd_hash(name      varchar2,
                        base      binary_integer,
                        hash_size binary_integer) return binary_integer;
      pragma interface(c, icd_hash);
    

    icd_hashをグーグルで検索しましょう _psdhshにマップされていることがわかります ( https://yurichev.com/blog/50/ )。次に、oracle.exeを分解し、_psdhshのコードを抽出します。 それから。多分私は来年これに少し時間を費やすでしょう。



    1. SQL ServerのCOUNT()とCOUNT_BIG():違いは何ですか?

    2. Asteriskサーバーをmysqlなどの外部リレーショナルデータベースと統合するにはどうすればよいですか?

    3. インターバルテーブルから秒を抽出/レコードをインターバルにキャストしますか?

    4. このmySQLクエリをPHPファイルに正しく実装して結果を表示するにはどうすればよいですか?