Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Cara tercepat untuk menghitung hash dari seluruh tabel

Pertama-tama, saya pikir cara mendekati "administrator nakal" adalah dengan kombinasi jejak audit Oracle dan Vault Basis Data fitur.

Yang mengatakan, inilah yang mungkin saya coba:

1) Buat fungsi agregat ODCI khusus untuk menghitung hash dari beberapa baris sebagai agregat.2) Buat VIRTUAL NOT NULL kolom pada tabel yang merupakan hash SHA dari semua kolom dalam tabel -- atau semua kolom yang ingin Anda lindungi. Anda akan menyimpan ini sepanjang waktu -- pada dasarnya menukar beberapa insert/update/delete kinerja sebagai gantinya untuk dapat menghitung hash lebih cepat.3) Buat indeks non-unik pada kolom virtual itu4) SELECT my_aggregate_hash_function(virtual_hash_column) FROM my_table untuk mendapatkan hasilnya.

Berikut kodenya:

Buat fungsi agregat untuk menghitung hash SHA pada sekumpulan baris

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;
/

Buat tabel uji untuk digunakan (Anda melewati ini karena Anda memiliki tabel asli)

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

Buat hash kolom virtual dari setiap data baris. Pastikan itu 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 ;

Buat indeks pada kolom virtual; dengan cara ini Anda dapat menghitung hash Anda dengan pemindaian penuh indeks sempit alih-alih pemindaian penuh tabel lemak

create index msi_compliance_hash_n1 on mattmsi (compliance_hash);  

Satukan semuanya untuk menghitung hash Anda

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

Beberapa komentar:

  1. Saya pikir penting untuk menggunakan hash untuk menghitung agregat (daripada hanya melakukan SUM() di atas hash tingkat baris, karena penyerang dapat memalsukan jumlah yang benar dengan sangat mudah.
  2. Saya rasa Anda tidak dapat (dengan mudah?) menggunakan kueri paralel karena penting bahwa baris dimasukkan ke fungsi agregat dalam urutan yang konsisten, atau nilai hash akan berubah.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Permintaan SQL dengan klarifikasi ON DUPLICATE KEY UPDATE diperlukan

  2. ORA-28040 Tidak ada protokol otentikasi yang cocok saat menghubungkan dari SQL PLUS ke Oracle 12c DB menggunakan sql plus klien versi 11.1

  3. kiri luar bergabung dengan nilai nol

  4. Kesalahan pekerjaan impor Sqoop org.kitesdk.data.ValidationException untuk Oracle

  5. Cara men-debug Prosedur Tersimpan Java di Oracle