Logo Oracle Deutschland   DBA Community  -   April 2015 (Update Juni 2015)
Automatic Big Table Caching in 12c
von Ulrike Schwinn, Oracle Deutschland B.V. & Co. KG

Bei der Betrachtung der Performance von Workloads gehört auch die Analyse des Cache Verhaltens von Daten zu den wichtigen Aspekten. Result Caching, das Pre Loading von Tabellen oder die Verwendung des Keep Pools sind altbekannte Techniken in diesem Zusammenhang. Gerade mit Oracle Database 12c (12.1.0.2) und der Einführung der In-Memory Database Option sind viele Neuigkeiten nicht nur für die Segment Ablage im Cache, sondern auch im Bereich optimierte Ausführung und somit zur Performance Steigerung hinzugefügt worden. Wer sich hierüber informieren möchte, sollte den interessanten Blog oder das White Paper zum Thema Oracle Database In-Memory von Maria Colgan zu rate ziehen.

Unabhängig von diesen Features ist eine weitere Neuigkeit eigens für das parallele oder serielle Scannen von Segmenten im Hauptspeicher eingeführt worden - das sogenannte Automatic Big Table Caching (auch kurz ABTC).

Die Idee dahinter ist einfach: Ein gewisser dedizierter Teil des Buffer Caches wird für die Speicherung großer Objekte oder Teile davon reserviert, so dass gewisse Abfragen von der Speicherung im Cache profitieren können, die ansonsten nicht im Buffer Cache vorliegen würden. Um zu entscheiden, welche Objekte im speziellen Big Table Cache gespeichert werden, nutzt ABTC mehrere Kriterien. Entscheidend für die Nutzung ist dabei nicht nur die Größe des Objekts und die Größe des Big Table Caches. Im Unterschied zum Standard Buffer Cache Verhalten, das auf dem Block Level orientierten LRU Algorithmus basiert, spielt die "Temperatur" der Objekte - nicht der Blöcke - bei der Nutzung des Big Table Caches eine wichtige Rolle.

Wichtig zu wissen ist, dass ABTC in Oracle Real Application Clusters (Oracle RAC) Umgebungen nur mit Parallel Query unterstützt wird; in Single Instance Umgebungen kann ABTC auch mit seriellen Abfragen verwendet werden. Zur Demonstration des Features wird im folgenden Abschnitt eine serielle Abfrage verwendet.

Setup und eine erste Beispielanwendung

Das Setup dazu ist einfach und im laufenden Betrieb möglich. Eingeschaltet wird das ABTC im Single Instance Umfeld über den Parameter DB_BIG_TABLE_CACHE_PERCENT_TARGET. Dieser Parameter reserviert einen dedizierten Anteil am Buffer Cache (in Prozent). Der Defaultwert ist 0; das Feature ist standardmässig also nicht eingeschaltet. Setzt man den Wert zum Beispiel auf 40, wird ca. 40 Prozent des Buffer Caches für ABTC verwendet; die restlichen 60 Prozent des Caches unterliegen dem Standardverhalten des Buffer Caches.

SQL> show parameter big
NAME				     TYPE	 VALUE
------------------------------------ ----------- ------------------------------
db_big_table_cache_percent_target    string	 0
Übrigens ist auch kein AUTO DOP eingeschaltet, wie folgender Ausschnitt zeigt.
SQL> show parameter parallel_degree_policy

NAME                     	     TYPE        VALUE
------------------------------------ ----------- ------------------------------
parallel_degree_policy               string      MANUAL
Um das Feature zu demonstrieren, nutzen wir nun eine einfache Abfrage auf die Tabelle SALES_COPY, die auch nach mehrmaliger Durchführung (hier dreifach) nicht im Buffer Cache gespeichert wird. Es wird ein Full Table Scan durchgeführt unter Verwendung von 35341 physical reads.
-- als User SH
SQL> set autotrace traceonly
SQL> select sum(prod_id) from sales_copy;
Execution Plan
----------------------------------------------------------
Plan hash value: 2728018880

---------------------------------------------------------------------------------
| Id  | Operation	   | Name	| Rows	| Bytes | Cost (%CPU)| Time	|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |		|     1 |     4 |  9629   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |		|     1 |     4 |	     |		|
|   2 |   TABLE ACCESS FULL| SALES_COPY |  7350K|    28M|  9629   (1)| 00:00:01 |
---------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
	  0  recursive calls
	  0  db block gets
      35346  consistent gets
      35341  physical reads
	  0  redo size
	550  bytes sent via SQL*Net to client
	551  bytes received via SQL*Net from client
	  2  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
	  1  rows processed
Zur Sicherheit überprüfen wir das Verhalten über V$BH. Zur Erinnerung: V$BH listet diejenigen Blöcke mit DATA_OBJECT_ID auf, die im Moment im Buffer Cache sind. In unserem Fall liegt 1 Block im Cache (siehe Spalte NUMBER_OF_BLOCKS).
SQL> SELECT o.object_name, o.object_type, o.owner, COUNT(*) NUMBER_OF_BLOCKS
     FROM dba_objects o, v$bh bh
     WHERE o.data_object_id = bh.objd
     AND (o.owner in ('SH'))
     GROUP BY o.object_name, o.owner, o.object_type
     ORDER BY COUNT(*);

OBJECT_NAME		  OBJECT_TYPE	  OWNER NUMBER_OF_BLOCKS
------------------------- --------------- ----- ----------------
SALES_COPY		  TABLE 	  SH		       1
Eine weitere Möglichkeit des Monitorings wäre die Session Statistiken hinzuzunehmen. Wie wir im nächsten Beispiel sehen können, wird für die Statistiken table scans (direct read) und table scans (long tables) der Wert 3 angegegeben. Es sind also 3 Table Scans auf eine Long Table - in unserem Beispiel SALES_COPY - durchgeführt worden; dabei erfolgten offensichtlich Direct Reads.
SQL> select username, s.serial#, n.name, value
     from v$statname n, v$session s, v$sesstat t
     where s.sid=t.sid
     and n.statistic# = t.statistic#
     and s.type = 'USER' and s.username!='SYS' and value!=0
     and (n.name like '%warehousing%' or n.name like '%table%') 
     and username='SH'  
     order by s.serial#, value desc

USERNAME	   SERIAL# NAME 					 VALUE
--------------- ---------- ---------------------------------------- ----------
SH		     20502 table scan rows gotten		       7354817
SH		     20502 table scan disk non-IMC rows gotten	       7354817
SH		     20502 table scan blocks gotten			 35414
SH		     20502 table fetch by rowid 			   132
SH		     20502 table scans (short tables)			    30
SH		     20502 table scans (direct read)			     3
SH		     20502 table scans (long tables)			     3
Um den neuen Big Table Cache zu überwachen, stehen sogar zwei weitere V$ Views zur Verfügung.
  • V$BT_SCAN_CACHE zeigt den Status der einzelnen Bereiche des Big Table Caches an.
  • V$BT_SCAN_OBJ_TEMPS listet aktive Objekte des Big Table Caches.
Beachten Sie, dass nicht alle Tabellen in der View V$BT_SCAN_OBJ_TEMPS angezeigt werden. Beispielsweise können sich auch kleinere Tabellen im Big Table Cache befinden ohne in V$BT_SCAN_OBJ_TEMPS gelistet zu werden.

Überprüfen wir zuerst den Inhalt der beiden Tabellen.
SQL> SELECT bt_cache_alloc, bt_cache_target, object_count, memory_buf_alloc, min_cached_temp 
     FROM v$bt_scan_cache;

BT_CACHE_ALLOC BT_CACHE_TARGET OBJECT_COUNT MEMORY_BUF_ALLOC MIN_CACHED_TEMP
-------------- --------------- ------------ ---------------- ---------------
	     0		     0		  0		   0		1000

SQL> SELECT o.object_name, cached_in_mem, size_in_blks, policy, temperature 
     FROM v$bt_scan_obj_temps bt, dba_objects o
     WHERE bt.dataobj#=o.object_id;

no rows selected
Das Ergebnis beider Abfragen zeigt, dass im Moment kein Big Table Caching verwendet wird. Die Spalten MIN_CACHED_TEMP und TEMPERATURE weisen darauf hin, dass intern eine Heatmap verwendet wird, um über die Objekte im Big Table Cache zu entscheiden. Der Wert in der Spalte MIN_CACHED_TEMP (hier 1000) gibt dabei die minimale Temperatur an, die ein Objekt haben muss, um im Big Table Cache gespeichert werden zu können.

Im nächsten Schritt setzen wir nun den Parameter DB_BIG_TABLE_CACHE_PERCENT_TARGET auf 40. Das bedeutet 40 Prozent des Buffer Caches wird für Scans und damit für den Big Table Cache verwendet; die verbleibenden 60 Prozent stehen für andere Workloads zur Verfügung.
SQL> ALTER SYSTEM SET db_big_table_cache_percent_target=40;

System altered
Nun wiederholen wir die Abfrage auf die Tabelle SALES_COPY und führen erneut Abfragen auf die beiden neuen V$ Views aus. Hinweis: Parallel dazu werden weitere Workloads und Scans durchgeführt.
SQL> SELECT bt_cache_alloc, bt_cache_target, object_count, memory_buf_alloc, min_cached_temp 
     FROM v$bt_scan_cache;

BT_CACHE_ALLOC BT_CACHE_TARGET OBJECT_COUNT MEMORY_BUF_ALLOC
-------------- --------------- ------------ ----------------
    .400005755		    40		  3	       50685
In der Spalte BT_CACHE_TARGET wird das Target von 40 Prozent angezeigt; BT_CACHE_ALLOC zeigt die aktuelle Ratio mit 0.400005 an. Drei Objekte werden offensichtlich im Big Table Cache gelistet. Insgesamt sind im Moment 50685 Memory Buffer dafür allokiert. Die zugehörigen Tabellen lassen sich dann über die View V$BT_SCAN_OBJ_TEMPS anzeigen. Damit die Namen der Objekte angezeigt werden, führen wir einen Join mit DBA_OBJECTS aus.
SQL> SELECT o.object_name, cached_in_mem, size_in_blks, policy, temperature 
     FROM v$bt_scan_obj_temps bt, dba_objects o
     WHERE bt.dataobj#=o.object_id;

OBJECT_NAME	     CACHED_IN_MEM SIZE_IN_BLKS POLICY	   TEMPERATURE
-------------------- ------------- ------------ ---------- -----------
FACT_PP_OUT_ITM_XXX	     41700	  44878 MEM_PART	185000
AB_ELEMENT_RELA 	      2644	   2644 DISK		  1000
SALES_COPY			 0	  35421 DISK		  5000
Die Tabelle FACT_PP_OUT_ITM_XXX ist fast vollständig in Memory (siehe Policy MEM_PART); die Tabellen SALES_COPY und AB_ELEMENT_RELA hingegen werden weiterhin von Disk gelesen (siehe Policy DISK). Die Entscheidung über das Cachen der Tabellen wird über den Spaltenwert TEMPERATURE gesteuert. Die minimale Temperatur liegt bei 1000, wie wir zu Beginn gesehen haben. Bei jedem Zugriff auf ein Objekt erhöht die Datenbank die Temperatur des entsprechenden Objekts, so dass nur ein Objekt das "hot" ist, für den Cache in Frage kommt. Ein Objekt im Big Table Cache kann dann nur von einem Objekt mit höherer Temperatur verdrängt werden. Ist der Big Table Cache nicht ausreichend groß - wie in unserem Fall können nur die Objekte mit der höchsten Temperatur gespeichert werden. Dabei kommt auch ein teilweises Cachen des Objekts in Frage.

Im nächsten Schritt vergrößern wir den Big Table Cache mit dem ALTER SYSTEM Befehl auf 70 Prozent. Schaut man sich nun die Resultate an, wird man veränderte Ergebnisse erhalten.
SQL> SELECT bt_cache_alloc, bt_cache_target, object_count, memory_buf_alloc, min_cached_temp 
     FROM v$bt_scan_cache;

BT_CACHE_ALLOC BT_CACHE_TARGET OBJECT_COUNT MEMORY_BUF_ALLOC
-------------- --------------- ------------ ----------------
    .700002878		    70		  3	       58009

SQL> SELECT o.object_name, cached_in_mem, size_in_blks, policy, temperature 
     FROM v$bt_scan_obj_temps bt, dba_objects o
     WHERE bt.dataobj#=o.object_id;

OBJECT_NAME	     CACHED_IN_MEM SIZE_IN_BLKS POLICY	   TEMPERATURE
-------------------- ------------- ------------ ---------- -----------
FACT_PP_OUT_ITM_XXX	     44878	  44878 MEM_ONLY	186000
AB_ELEMENT_RELA 	      2644	   2644 DISK		  1000
SALES_COPY		     35421	  35421 MEM_ONLY	  6000
Die Tabellen FACT_PP_OUT_ITM_XXX und SALES_COPY liegen nun vollständig im Big Table Cache vor. Auch die Überprüfung der Ausführungsstatistiken kann das Ergebnis bzgl. der Tabelle SALES_COPY bestätigen.
-- als User SH
SQL> select sum(prod_id) from sales_copy;

Execution Plan
----------------------------------------------------------
Plan hash value: 2728018880

---------------------------------------------------------------------------------
| Id  | Operation	   | Name	| Rows	| Bytes | Cost (%CPU)| Time	|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |		|     1 |     4 |  9629   (1)| 00:00:01 |
|   1 |  SORT AGGREGATE    |		|     1 |     4 |	     |		|
|   2 |   TABLE ACCESS FULL| SALES_COPY |  7350K|    28M|  9629   (1)| 00:00:01 |
---------------------------------------------------------------------------------

Statistics
----------------------------------------------------------
	  0  recursive calls
	  0  db block gets
      35354  consistent gets
	  0  physical reads
	  0  redo size
	550  bytes sent via SQL*Net to client
	551  bytes received via SQL*Net from client
	  2  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
	  1  rows processed
Nach einiger Zeit wurden die beiden Abfragen wieder ausgeführt. Mittlerweile sind 12 Objekte (siehe OBJECT_COUNT) im Big Table Cache. Die Temperatur der beiden Tabellen im Big Table Cache hat sich verringert, weil kein Zugriff mehr erfolgte.
SQL> SELECT bt_cache_alloc, bt_cache_target, object_count, memory_buf_alloc, min_cached_temp 
     FROM v$bt_scan_cache;

BT_CACHE_ALLOC BT_CACHE_TARGET OBJECT_COUNT MEMORY_BUF_ALLOC
-------------- --------------- ------------ ----------------
    .700002878		    70		 12	       72976

SQL> 
SQL> SELECT o.object_name, cached_in_mem, size_in_blks, policy, temperature 
     FROM v$bt_scan_obj_temps bt, dba_objects o
     WHERE bt.dataobj#=o.object_id;

OBJECT_NAME		       CACHED_IN_MEM SIZE_IN_BLKS POLICY     TEMPERATURE
------------------------------ ------------- ------------ ---------- -----------
FACT_PP_OUT_ITM_XXX		       44878	    44878 MEM_ONLY	  168500
SALES_COPY			       35421	    35421 MEM_ONLY	    1000
Falls sie mit partitionierten Tabellen zu tun haben, ergänzen Sie die Spalte SUBOBJECT_NAME aus DBA_OBJECTS.

Monitoren lässt sich das Ganze auch wieder wie oben über die Session Statistiken. Mittlerweile haben wir die Abfrage auf SALES_COPY noch zweimal durchgeführt. Die Statistiken für "table scans (direct read)" und "table scans (long tables)" bleiben gleich, stattdessen erhöht sich die Statistik "table scans (short tables)" von 30 auf 32. Zusätzlich gibt es neue Statistiken mit Namen "data warehousing scanned blocks%'. Wie man erkennen kann, steht der Wert für die Statistik "data warehousing scanned objects" auf 2.
SQL> select username, s.serial#, n.name, value
     from v$statname n, v$session s, v$sesstat t
     where s.sid=t.sid
     and n.statistic# = t.statistic#
     and s.type = 'USER' and s.username!='SYS' and value!=0
     and (n.name like '%warehousing%' or n.name like '%table%') 
     and username='SH'  
     order by s.serial#, value desc;

USERNAME	   SERIAL# NAME 					 VALUE
--------------- ---------- ---------------------------------------- ----------
SH		     20502 table scan disk non-IMC rows gotten	      29407049
SH		     20502 table scan rows gotten		      29407049
SH		     20502 table scan blocks gotten			141437
SH		     20502 data warehousing scanned blocks		 35341
SH		     20502 data warehousing scanned blocks - memory	 35341
SH		     20502 table fetch by rowid 			   132
SH		     20502 table scans (short tables)			    32
SH		     20502 table scans (direct read)			     3
SH		     20502 table scans (long tables)			     3
SH		     20502 data warehousing scanned objects		     2


Verwendung im RAC Umfeld

Im Gegensatz zur Single Instance Implementierung wird das Automatic Big Table Caching in Oracle Real Application Clusters (Oracle RAC) Umgebungen nur von parallelen Abfragen unterstützt. Voraussetzung zur Verwendung ist in diesem Fall das Setzen von zwei Parametern:
  • PARALLEL_DEGREE_POLICY muss den Wert AUTO oder ADAPTIVE (neu in 12c) haben.
  • DB_BIG_TABLE_CACHE_PERCENT_TARGET gibt den Prozentsatz des Database Buffer Caches zur Verwendung an.
ABTC nutzt - wie wir im ersten Beispiel schon teilweise gesehen haben - spezielle Algorithmen und Entscheidungskriterien, um den Big Table Cache optimal zu verwenden. Falls ein Objekt den Anforderungen des Big Table Caches nicht genügt, wird es via Direct Path IO ausgeführt. Weitere Informationen dazu kann man auch im White Paper "Parallel Execution with Oracle Database 12c" lesen.

Zitat: The size of objects that are eligible to be cached can be up to three times larger than the available reserved memory. ABTC uses an optimized segment and temperature-based algorithm to ensure the most optimal usage of the available cache...
With in-memory PX and ABTC the database decides if the objects accessed by the statement should be cached in ABTC or not. An object can either be a table, an index, or in the case of partitioned objects one or more partitions. This decision is based on an advanced set of heuristics that include the size of an object, the frequency at which the object is accessed, and the size of ABTC. If the object meets these criteria in-memory processing will be enabled and the accessed object will be cached in ABTC




In RAC Umgebungen mit mehreren Nodes wird das Objekt bzw. werden die Fragmente eines Objekts auf die Nodes verteilt; dabei handelt es sich um Partitionen oder auch nur um Reihe von Blöcken eines Tabellen Segments. Die Graphik oben (Quelle: White Paper December 2014: Parallel Execution with Oracle Database 12c Fundamentals) illustriert diese Verteilung an einem Beispiel.
Hinweis: Setzt man PARALLEL_FORCE_LOCAL auf TRUE, wird dieser Cache allerdings nicht "geshared", sondern mehrfach auf den Instanzen allokiert.

Lizenzierungshinweis

ABTC mit seriellen Abfragen im Single Instance Umfeld steht in allen Editionen zur Verfügung. Wird ABTC für parallele und serielle Abfragen im RAC oder Single Instance Umfeld verwendet, ist die Enterprise Edition erforderlich.

Weitere Informationen

Zurück zur Community-Seite