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

テーブル全体のハッシュを計算する最速の方法

    まず、「不正な管理者」にアプローチする方法は、Oracleの監査証跡を組み合わせることだと思います。 およびデータベースボールト 機能。

    そうは言っても、これが私が試すかもしれないことです:

    1)カスタムODCI集計関数を作成して、複数の行のハッシュを集計として計算します。2)VIRTUAL NOT NULLを作成します。 テーブル内のすべての列のSHAハッシュであるテーブル上の列-または保護する必要のあるすべての列。あなたはこれを常に維持するでしょう-基本的にいくつかのinsert/update/deleteをトレードオフします ハッシュをより迅速に計算できるようにする代わりにパフォーマンス。3)その仮想列に一意でないインデックスを作成する4)SELECT my_aggregate_hash_function(virtual_hash_column) FROM my_table 結果を得るために。

    コードは次のとおりです:

    一連の行に対してSHAハッシュを計算するための集計関数を作成します

    CREATE OR REPLACE TYPE matt_hash_aggregate_impl AS OBJECT
    (
      hash_value RAW(32000),
      CONSTRUCTOR FUNCTION matt_hash_aggregate_impl(SELF IN OUT NOCOPY matt_hash_aggregate_impl ) RETURN SELF AS RESULT,  
    -- Called to initialize a new aggregation context
    -- For analytic functions, the aggregation context of the *previous* window is passed in, so we only need to adjust as needed instead 
    -- of creating the new aggregation context from scratch
      STATIC FUNCTION ODCIAggregateInitialize (sctx IN OUT matt_hash_aggregate_impl) RETURN NUMBER,
    -- Called when a new data point is added to an aggregation context  
      MEMBER FUNCTION ODCIAggregateIterate (self IN OUT matt_hash_aggregate_impl, value IN raw ) RETURN NUMBER,
    -- Called to return the computed aggragate from an aggregation context
      MEMBER FUNCTION ODCIAggregateTerminate (self IN matt_hash_aggregate_impl, returnValue OUT raw, flags IN NUMBER) RETURN NUMBER,
    -- Called to merge to two aggregation contexts into one (e.g., merging results of parallel slaves) 
      MEMBER FUNCTION ODCIAggregateMerge (self IN OUT matt_hash_aggregate_impl, ctx2 IN matt_hash_aggregate_impl) RETURN NUMBER,
      -- ODCIAggregateDelete
      MEMBER FUNCTION ODCIAggregateDelete(self IN OUT matt_hash_aggregate_impl, value raw) RETURN NUMBER  
    );
    
    /
    
    CREATE OR REPLACE TYPE BODY matt_hash_aggregate_impl IS
    
    CONSTRUCTOR FUNCTION matt_hash_aggregate_impl(SELF IN OUT NOCOPY matt_hash_aggregate_impl ) RETURN SELF AS RESULT IS
    BEGIN
      SELF.hash_value := null;
      RETURN;
    END;
    
    
    STATIC FUNCTION ODCIAggregateInitialize (sctx IN OUT matt_hash_aggregate_impl) RETURN NUMBER IS
    BEGIN
      sctx := matt_hash_aggregate_impl ();
      RETURN ODCIConst.Success;
    END;
    
    
    MEMBER FUNCTION ODCIAggregateIterate (self IN OUT matt_hash_aggregate_impl, value IN raw ) RETURN NUMBER IS
    BEGIN
      IF self.hash_value IS NULL THEN
        self.hash_value := dbms_crypto.hash(value, dbms_crypto.hash_sh1);
      ELSE 
          self.hash_value := dbms_crypto.hash(self.hash_value || value, dbms_crypto.hash_sh1);
      END IF;
      RETURN ODCIConst.Success;
    END;
    
    MEMBER FUNCTION ODCIAggregateTerminate (self IN matt_hash_aggregate_impl, returnValue OUT raw, flags IN NUMBER) RETURN NUMBER IS
    BEGIN
      returnValue := dbms_crypto.hash(self.hash_value,dbms_crypto.hash_sh1);
      RETURN ODCIConst.Success;
    END;
    
    MEMBER FUNCTION ODCIAggregateMerge (self IN OUT matt_hash_aggregate_impl, ctx2 IN matt_hash_aggregate_impl) RETURN NUMBER IS
    BEGIN
        self.hash_value := dbms_crypto.hash(self.hash_value || ctx2.hash_value, dbms_crypto.hash_sh1);
      RETURN ODCIConst.Success;
    END;
    
    -- ODCIAggregateDelete
    MEMBER FUNCTION ODCIAggregateDelete(self IN OUT matt_hash_aggregate_impl, value raw) RETURN NUMBER IS
    BEGIN
      raise_application_error(-20001, 'Invalid operation -- hash aggregate function does not support windowing!');
    END;  
    
    END;
    /
    
    CREATE OR REPLACE FUNCTION matt_hash_aggregate ( input raw) RETURN raw
    PARALLEL_ENABLE AGGREGATE USING matt_hash_aggregate_impl;
    /
    

    使用するテストテーブルを作成します(実際のテーブルがあるため、これはスキップします)

    create table mattmsi as select * from mtl_system_items where rownum <= 200000;
    

    各行のデータの仮想列ハッシュを作成します。 NOT NULLであることを確認してください

    alter table mattmsi add compliance_hash generated always as ( dbms_crypto.hash(to_clob(inventory_item_id || segment1 || last_update_date || created_by || description), 3 /*dbms_crypto.hash_sh1*/) ) VIRTUAL not null ;
    

    仮想列にインデックスを作成します。このようにして、ファットテーブルのフルスキャンではなく、ナローインデックスのフルスキャンを使用してハッシュを計算できます

    create index msi_compliance_hash_n1 on mattmsi (compliance_hash);  
    

    すべてをまとめてハッシュを計算します

    SELECT matt_hash_aggregate(compliance_hash) from (select compliance_hash from mattmsi order by compliance_hash);
    

    いくつかのコメント:

    1. SUM()を実行するだけでなく、ハッシュを使用して集計を計算することが重要だと思います。 攻撃者が正しい合計を非常に簡単に偽造する可能性があるため、行レベルのハッシュを超えます。
    2. (簡単に?)並列クエリを使用できるとは思いません 行を一貫した順序で集計関数にフィードすることが重要であるためです。そうしないと、ハッシュ値が変更されます。


    1. UTF-8、PHP、およびXML Mysql

    2. 非LOB列を更新する必要があるかどうかの確認

    3. java-Oracleストアドプロシージャで配列を渡す

    4. json_encode()メソッドにメモリ制限はありますか?