Warning: Declaration of Suffusion_MM_Walker::start_el(&$output, $item, $depth, $args) should be compatible with Walker_Nav_Menu::start_el(&$output, $item, $depth = 0, $args = Array, $id = 0) in /DISK2/WWW/plsql.cz/www/wp-content/themes/suffusion/library/suffusion-walkers.php on line 0
Sep 172012
 

Porovnat obsah dvou tabulek není nic těžkého – v té nejjednodušší podobě se udělá některá z množinových operací a výsledek je hotov. Podobně napsání scriptu na sychronizaci rozdílných tabulek není žádný challenge.  Druhá možnost jak zjistit jestli data v tabulkách jsou stejná je použít nativní funkcionalitu Oracle a package s názvem DBMS_COMAPRSION. S tímto package míří Oracle na distribuované databáze a primárním účlem je porovnávat tabulky z rozdílných databází (pochopitelně větší výkon než nejhloupější script s množinvou operací “mínus”). Pokud se však parametr databázového linku nevyplní (tzn. NULL) či se vyplní loopbackovým databázovým linkem – lze porovnávat dva objekty v téže databázi. Objekty proto, že to nezbytně nutně nemusí být tabulka, DBMS_COMPARSION porovnává:

  • Tabulky
  • Single-table pohledy
  • Materializované pohledy
  • A synonyma pro předchozí objekty, tedy tabulky, single-table pohledy a materializované pohledy.

Naopak existují také omezení, mimo logických jakým je například rozdílně nastavené NLS na lokální a cílové databázi a sloupce s informací o TIME_ZONE, jsou to také restrikce technologické, především pro porovnávané tabulky které obsahují sloupce typu: ROWID, LOBy, LONG, LONG RAW, BFILE, uživatelsky definované typy a další složité typy (XMLType apod.) Nimcméně jako při vytváření ERROR LOG tabulky je možnost přeskočit “unsupported columns” a tedy porovnat objekty s tím, že nepodporované sloupce jsou omitnuty.

Dále vždy důležité warnings: Není to transakčně konzistentní na databázích po linku – tedy pokud se po scanu první tabulky změní data, výsledek nemusí mít to co bychom čekali. Primárně je funkcionalita určena na Oracle Stremas, například na odkontrolvání složitějšího APPLY.

K čemu je to dobré, jak se to dá použít i nějaké ty konstrainy a warningy tu jsou a nyní k tomu nejzábavnějšímu. Nejprve tedy nějakou tabulku na test – zdrojová:

CREATE TABLE SOURCE_TBL (
ID NUMBER PRIMARY KEY,
ENERGY_DRINK VARCHAR(20)
);

insert into SOURCE_TBL values (1,‘Monster Energy’);
insert into SOURCE_TBL values (2,‘Rockastar’);
insert into SOURCE_TBL values (3,‘Red bull’);
insert into SOURCE_TBL values (4,‘Shock’);
commit;

A tabulka se kterou ji budeme zakládat (struktura stejná, odlišná data)

CREATE TABLE TARGET_TBL (
ID NUMBER PRIMARY KEY,
ENERGY_DRINK VARCHAR(20)
);

insert into TARGET_TBL values (1,‘Monster Energy – Ripper’);
insert into TARGET_TBL values (2,‘Rockastar – Xdurance’);
insert into TARGET_TBL values (4,‘Shock’);
insert into TARGET_TBL values (5,‘Playboy Energy Drink’);
commit;

Nyní je třeba založit objekt “COMPARSION”, podobně jako se u advisoru zakládají tasky apod. COMPARSION se vytváří pomocí procedury DBMS_COMPARSION.CREATE_COMPARSION, tedy:

BEGIN
DBMS_COMPARISON.CREATE_COMPARISON(
comparison_name=>'COMPARSION_ENERGY_DINKS',
schema_name =>'HAF',
object_name => 'SOURCE_TBL',
dblink_name =>null,
index_schema_name=>null,
index_name =>null,
remote_schema_name =>'HAF',
remote_object_name =>'TARGET_TBL',
comparison_mode =>DBMS_COMPARISON.CMP_COMPARE_MODE_OBJECT,
column_list =>'*',
scan_mode =>DBMS_COMPARISON.CMP_SCAN_MODE_FULL,
scan_percent =>null,
null_value =>DBMS_COMPARISON.CMP_NULL_VALUE_DEF,
local_converge_tag => null,
remote_converge_tag =>null,
max_num_buckets =>2,
min_rows_in_bucket =>2);
END;

První spuštení procedury v Oracle patrně potrvá poněkud déle (až minuty), databáze potřebuje založit pohledy a objekty, které v DB, které nejsou založeny by default po instalaci. A nyní k parametrům:

  • comparison_name – nic překvapivého VARCHAR2, jméno comparsion
  • schema_name,object_name,dblink_name,index_schema_name,index_name,remote_schema_name a remote_object_name asi není třeba kommentovat
  • comparison_mode – konstanta DBMS_COMPARISON.CMP_SCAN_MODE_FULL  parametr má možnou jedinou tuto hodnotu, nové mody mohou být přidány v budoucnu zní poznámka
  • column_list - sloupce na kterých se bude porovnávat, zástupný znak * pro všechny
  • scan_mode – CMP_SCAN_MODE_FULL, CMP_SCAN_MODE_RANDOM, CMP_SCAN_MODE_CYCLIC nebo CMP_SCAN_MODE_CUSTOM
  • scan_percent – není třeba porovnávat celou tabulku, lze například cyklicky či náhodně a nějaké procento
  • null_value - pokud je uvedeno, cílový sloupec s tout hodnotou “odpovídá” hodnotě null. Hodnota nahrazující null
  • local_converge_tag  a remote_converge_tag - pro Oracle Streams
  • max_num_buckets – porovnává se po částech
  • max_rows_in_bucket – maximální velkost části

Po spuštění se vytvoří COMPARSION s názvem : COMPARSION_ENERGY_DRINKS, lze si prohlédnout v pohledu USER_COMPARSIONS, kde není nic jiného než založený záznam pro každé COMPARSION a jeho parametry a sloupec  LAST_UPDATE_TIME typu timpestamp, jehož název mluví za vše.

Dále je tu pohled USER_COMPARSION_COLUMNS ve kterém jsou uvedeny sloupce ke každému COMPARSION a jestli je na nich INDEX.

A nyní zbývá spustit proceduru DBMS_COMPARSION.COMPARE k vlastnímu porovnání tabulek SOURCE_TBL a TARGET_TBL.

DECLARE
t_info DBMS_COMPARISON.comparison_type;
res BOOLEAN;
BEGIN
res:=DBMS_COMPARISON.COMPARE(
comparison_name=>'COMPARSION_ENERGY_DINKS',
scan_info =>t_info,
min_value =>NULL,
max_value =>NULL,
perform_row_dif=>TRUE);
dbms_output.put_line(case when res then 'TRUE' else 'FALSE' end);
dbms_output.put_line('loc_rows_merged '||t_info.scan_id);
dbms_output.put_line('loc_rows_merged '||t_info.loc_rows_merged);
dbms_output.put_line('rmt_rows_merged '||t_info.rmt_rows_merged);
dbms_output.put_line('loc_rows_deleted '||t_info.loc_rows_deleted);
dbms_output.put_line('rmt_rows_deleted '||t_info.rmt_rows_deleted);
END;

A výstup je následující:
FALSE
loc_rows_merged 1
loc_rows_merged 0
rmt_rows_merged 0
loc_rows_deleted 0
rmt_rows_deleted 0

False řiká, že tabulky nejsou stejné a výpis z typu comparison_type jaké rozdíly tam jsou. Oracle však reportuje v tomto typu pouze hodnoty dle bucketů, proto dle nastavení nemusí odpovidat (a typicky nebudou) počtu řádků.  Jaký je výsledek scanu (spuštěním COMPARE) lze vysledovat ve view USER_COMPARSION_SCAN:  select * from user_comparsion_scan:

Comparsion

Ještě detailnější pohled přímo na rozdílné sloupce poskytuje pohled USER_COMPARISON_SCAN_VALUE, select * from user_comparsion_scan_values:

user_comparsion_values

Posledním zajímavým pohledem je USER_COMPARSION_ROW_DIF, který zobrazuje rozdílné řádky(šikovné samo o sobě, že?). select * from user_comparsion_row_dif;

user_comparsion_row_dif

Spuštěním COMPARE je hotový scan, nejsou však provedeny žádné DML změny nad tabulkama a data jsou taková jaká byla před scanem. Od promítnutí dat je tu procedura CONVERGE, tedy:

BEGIN
DBMS_COMPARISON.CONVERGE(
comparison_name=>'COMPARSION_ENERGY_DINKS',
scan_id=>1,
scan_info=> t_info,
converge_options => DBMS_COMPARISON.CMP_CONVERGE_LOCAL_WINS,
perform_commit=>TRUE,
local_converge_tag =>NULL,
remote_converge_tag=>NULL);
dbms_output.put_line('loc_rows_merged '||t_info.scan_id);
dbms_output.put_line('loc_rows_merged '||t_info.loc_rows_merged);
dbms_output.put_line('rmt_rows_merged '||t_info.rmt_rows_merged);
dbms_output.put_line('loc_rows_deleted '||t_info.loc_rows_deleted);
dbms_output.put_line('rmt_rows_deleted '||t_info.rmt_rows_deleted);
END;

Výsledek:
loc_rows_merged 1
loc_rows_merged 0
rmt_rows_merged 3
loc_rows_deleted 0
rmt_rows_deleted 1

K parametrům DBMS_COMPARSION.CONVERGE

  • comparsion_name – jméno COMPARSION
  • scan_id – každý comparsion může mít více scannů, tedy scan_id podle kterého se bude “mergovat”
  • scan_info OUT parametr s počty záznamů a jejich operacemi – viz výstup
  • coverge_options – pokud jsou na primálním klíči rozdílné řádky v obou porovávaných tabulkách, tak která vyhraje, možné dvě hodnoty CMP_CONVERGE_LOCAL_WINS a CMP_CONVERGE_REMOTE_WINS
  • perform_commit – název mluví za sebe, ovšem commit nezbytně nutně nemusí být jeden, v závislosti na nastavení (bulky)
  • local_converge_tag,remote_converge_tag – pro Oracle Streams

A nyní ještě pohled na data:

Comparsion výsledek

Comparsion výsledek

 Paráda, ne?

 Posted by at 19:09

 Leave a Reply

(required)

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>