Oracle 12c In-Memory Option Patchset 12.1.0.2

Oracle 12c mit In-Memory Option im Patchset 12.1.0.2 veröffentlicht

Am 22. Juli 2014 veröffentlichte Oracle Inc. das erste Patchset (12.1.0.2.0) für die 12c Datenbank.

Das Patchset enthält viele interessante neue Features, die es Wert sind, genauer unter die Lupe genommen zu werden.

  • Die bereits im Vorjahr auf der OpenWorld angekündigte In-Memory Option ist nun verfügbar.
    Die In-Memory Option enthält folgende Funktionalitäten:

    • In-Memory Column Store (Link)
    • Fault Tolerant In-Memory Column Store (setzt Exadata oder Supercluster voraus)
    • In-Memory Aggregation (Link)
    • ACHTUNG: Die In-Memory Option ist eine Option der Enterprise Edition und kann daher zu zusätzlichen Lizenzkosten führen (Link)
  • Force Full Caching Mode
    • Force Caching ist nun für alle Objekte möglich (Link)
    • Überprüfen Sie vorab, ob die Größe Ihre Datenbank in die SGA passt und aktivieren Sie dieses neue Features (ALTER DATABASE FORCE FULL DATABASE CACHING)
  • Automatic Big Table Caching
    • Dieses neue Feature ermöglicht es, große Tabellen in einem separaten Buffer zu speichern. Dadurch können Cache Rotations verhindert werden. (Link)
    • Der Big Table Cache ist ein Prozentteil des BUFFER CACHE. Es macht daher Sinn, die Memory Size zu überprüfen (zum Aktivieren verwenden Sie den DB_BIG_TABLE_CACHE_PERCENT_TARGET Paramteter)
    • Das Feature wird für Parallel Query beim RAC mit PARALLEL_DEGREE_POLICY auf AUTO oder ADAPTIVE unterstützt.
    • Auch auf Single Instanzenen für Single und Prallel Query
  • Advanced Index Compression
    • Ermöglicht Indexes auf effiziente Art zu komprimieren (Link)
    • Achtung: Dieses neue Features ist Teil der Advanced Compression Option kann daher zu zusätzlichen Lizenzkosten führen (Link)
  • READ Privilege
    • In früheren Releases gab es oft Probleme mit Usern, die das SELECT Recht auf spezielle Tables gegranted hatten. Dadurch ware es möglich, dass Tabellen in Exclusive Mode gelocked waren oder eine SELECT … FOR UPDATE möglich war. (Link)  Die neue Berechtigung “READ” wurde eingeführt und diese Problematik in Zukunft zu verhindern. (Link)
  • Viele neue Features für CDB und PDBs:
    • Flashback Data Archive (FDA) Unterstützung für CDBs (Link)
    • PDB CONTAINERS Clause
      • Query tables in einenm Subset von PDBs (Link)
    • PDB File Placement in OMF (Link)
    • PDB Logging Clause
      • Turn on NOLOGGING // LOGGING for the whole PDB (Link)
    • PDB Metadata Clone (Link)
    • PDB Remote Clone
      • Ein PDB // Non-CDB über einen Datenbank Link Clonen? Ja, natürlich ist das möglich (Link)
    • PDB Subset Cloning
      • Die USER_TABLESPACES Clause spezifiziert welcher Tablespace in der Plugable Database (PDB) verfügbar sein soll (Link)
    • PDB STANDBYS Clause (Link)
    • PDB State Management Across CDB restart. Dieses Features hat in der 12.1.0.1 wirklich gefehlt. Details hier oder eine Beschreibung des alten Problems finden Sie hier)

Abgesehen von dieser Aufzählung gibt es noch zahlreiche zustätzliche neue Features, die im Feature Guide aufgelistet sind (Link)

 

select blobs über Datenbank Link

Große BLOBs über einen Datenbank Link selektieren

Heute habe ich versucht ein BLOB über einen Datenbank Link zu selektieren.

Ich weiß, es gibt in solchen Fällen einige Einschränkungen, aber in diesem Fall gab mir der Business Case keine andere Wahl.

Mein Ziel war daher die BLOBs über einen Datenbank Link transparent zu selektieren. Einen passenden Workaround konnte ich nicht finden. Von support.oracle.com kam folgendes Statement:

 

  • SELECT with a LOB and DBLink Returns an ORA-22992: Cannot Use LOB Locators Selected from Remote tables (Doc ID 1234893.1)
    • “The error is expected because the use of DBLinks and LOBs via the SELECT from PL/SQL is not supported.”
  • Ora-22992 workaround (Doc ID 436707.1)
    • Getting ORA-1406 with lobs greater than 32KB – 1
  • ORA-1406: Fetched Column Value was Truncated When Selecting Remote Column into Local BLOB Variable (Doc ID 459557.1)
    • “This means that we are not able to retrieve BLOBs columns greater than 32KB – 1 in size through a database link.”

Zusammengefasst bedeutet diese Aussage, dass ein BLOB nativ über einen Datenbank Link nicht selektiert werden kann, falls dieser großer als 32KB-1 ist. Interessante Tatsache in diesem Zusammenhang ist, dass man DBMS_LOB Operators auf der lokalen und remoten Seite verwenden kann.

Mein persönlicher Favorit ist die DBMS_LOB.SUBSTR Funktion. Der Name der Funktion ist etwas ungenau, denn man kann damit BLOBs und auch CLOBs ansprechen.

 

Daraus hat sich mein folgender Ansatz ergeben, um BLOBs über einen Datenbank Link selektieren zu können:

Lösung VERSION 1 (Chunk Methode):

create or replace function GETBLOBVIADBLINK
( dblnk in varchar2
  ,tbl  in varchar2
  ,col  in varchar2
  ,rwid in urowid)
return blob
is
  retval blob;
  tmpraw raw(2000);  
  tmplen number;
  tmpchk number;
  chksize number;
begin
  --preset vars
  chksize:=2000;
  dbms_lob.createtemporary (retval,true);
  execute immediate 'select dbms_lob.getlength@'||dblnk||' ('||col||') from '||tbl||'@'||dblnk||' where rowid=:rwid' into tmplen using rwid;
  
  -- precalc  
  tmpchk:=floor(tmplen/chksize);

  -- applicate frist chunks  
  for i in 0 .. tmpchk-1
  loop  
    execute immediate 'select dbms_lob.substr@'||dblnk||'('||col||','||chksize||','||((i*chksize)+1)||') from '||tbl||'@'||dblnk||' where rowid=:rwid' into tmpraw using rwid;
    dbms_lob.append(retval,tmpraw);
  end loop;
  
  -- applicate last entry
  if (tmplen-(tmpchk*chksize)) > 0 then
    execute immediate 'select dbms_lob.substr@'||dblnk||'('||col||','||(tmplen-(tmpchk*chksize))||','||((tmpchk*chksize)+1)||') from '||tbl||'@'||dblnk||' where rowid=:rwid' into tmpraw using rwid;
    dbms_lob.append(retval,tmpraw);
  end if;
  return retval;
end;
/

Die Erklärung der Funktion ist sehr einfach:

  1. Ein TEMP LOB auf der lokalen Seite erstellen
  2. Die Limitation von DBMS_LOB.SUBSTR als RAW(2000) als mximale chunk size definieren
  3. Die einzelnen Chunks (max 2000 bytes) über den Datenbank Link kopieren und mit den Chunks auf der lokalen Seiten temporär ein BLOB zusammenfügen
  4. Das BLOB lokal auf dem Aufrufer übergeben

In Anschluss daran eine VIEW mit den neuen Definitionen erstellen:

CREATE OR REPLACE FORCE VIEW TESTVW1 (ID, MYLOB) AS 
SELECT id
       ,getblobviadblink('ARCHIV','MYLOBTABLE','MYLOB',rowid) MYLOB
FROM  MYLOB@archiv;

Fertig.
Nun ist es möglich über einen Datenbank Link auch größere BLOBs als 32KB-1 zu selektieren!

 

Es gibt aber auch noch andere Lösungswege:

Lösung VERSION 2 (temporary table Methode)

create global temporary table tmplob (tmplob blob) ON COMMIT PRESERVE ROWS;
create or replace function getblobviadblink2
( dblnk in varchar2
  ,tbl  in varchar2
  ,col  in varchar2
  ,rwid in urowid)
return blob
is
  PRAGMA AUTONOMOUS_TRANSACTION;
  retval blob;
begin

  execute immediate 'insert /*+ NOLOGGING */ into tmplob select '||col||' from '||tbl||'@'||dblnk||' where rowid=:rwid' using rwid;
  select tmplob into retval from tmplob;
  delete /*+ NOLOGGING */ from tmplob;
  commit;
  return retval;
end;
/

Beide Methoden sind möglich, aber die Version 2 ist wesentlich schneller.

Darüber hinaus gibt es sicherlich auch noch andere Lösungsmöglichkeiten.

Ich würde mich freuen, wenn Sie im Kommentar Ihre Erfahrungen posten.