Logo Oracle Deutschland   Datenbank Community  -   Januar 2016
Full Database Caching in 12c
von Ulrike Schwinn, Oracle Deutschland B.V. & Co. KG

Die Datenbank übernimmt seit jeher automatisch das Caching von Datenbankblöcken im Database Buffer Cache. Der Cache unterliegt dabei unterschiedlichen Algorithmen, was die Dauer und die Lagerung der Blöcke im Buffer Cache angeht. So werden beispielsweise die Blöcke nach einen Least Used Algorithmus im Cache gehalten, um die Verweildauer im Cache effizient zu gestalten oder können nach der Temperaturmethode (siehe Feature Automatic Big Table Caching) ausgelagert werden. Ein Table Scan auf kleinen (SMALL) Tabellen (in der Regel kleiner als 2% des Buffer Caches) wird dabei im Buffer Cache realisiert. Parallele und serielle Table Scans auf großen Tabellen werden hingegen über Direct Read Operationen realisiert. Large Objects (auch LOBs) - also SecureFiles oder BasicFiles (in der 12c Terminologie) - werden übrigens standardmässig nicht im Cache gespeichert. Dies sind ein paar Regeln, die man kennen sollte.

Neu in 12c ist ein automatischer Full Database Caching Mode. Falls das Memory ausreichend für die gesamte Datenbank ist und bestimmte interne Regeln erfüllt sind, werden alle Tabellen als kleine (SMALL) Tabellen angesehen und im Cache gelagert oder wie im Concepts Guide nachzulesen ist:
"Starting in Oracle Database 12c Release 1 (12.1.0.2), the buffer cache of a database instance automatically performs an internal calculation to determine whether memory is sufficient for the database to be fully cached in the instance SGA, and if caching tables on access would be beneficial for performance. If the whole database can fully fit in memory, and if various other internal criteria are met, then Oracle Database treats all tables in the database as small tables, and considers them eligible for caching. However, the database does not cache LOBs marked with the NOCACHE attribute."

Möchte man unabhängig von diesen Regeln sein, kann man diesen Modus auch forcieren. Das Konzept nennt sich dann Force Full Database Caching. Die Idee dahinter ist im Prinzip die gleiche wie beim automatischen Full Database Caching: Ist der Cache groß genug um alle Objekte im Cache zu speichern, können alle Objekte im Cache gelagert werden - allerdings einschließlich der LOB Objekte. Um den Full Database Mode zu nutzen, muss dieser zusätzlich im MOUNT Stadium der Datenbank separat eingeschaltet werden.

Dieses Feature steht übrigens in allen Editionen zur Verfügung und ist somit auch gut geeignet für "kleine" Standard Edition Datenbanken.

Das Setup

"Force Full Database Caching" wird wie der Name schon anzeigt, nicht automatisch aktiviert, sondern muss explizit vom Administrator im MOUNT Stadium der Datenbank eingeschaltet werden. In einer Multitenant Umgebung bezieht sich diese Einstellung auf alle PDBS - dies ist also eine "Container"- weite Entscheidung.

Um in meiner Beispielumgebung das Ganze zu demonstrieren, überprüfe ich zuerst den genutzten Speicher in der Datenbank und das zur Verfügung stehende Memory. Offensichtlich ist der Buffer Cache ausreichend konfiguriert.

SQL> select sum(bytes)/1024/1024 MB from dba_segments;

        MB
----------
  640.8125


SQL> select sum(bytes)/1024/1024 MB from dba_data_files;

        MB
----------
      1593


SQL> SELECT name, bytes/1024/1024 FROM V$SGAINFO where name = 'Buffer Cache Size';

NAME				 BYTES/1024/1024
-------------------------------- ---------------
Buffer Cache Size			    1936

Danach schalten wir den Full Database Mode im MOUNT Stadium der Datenbank ein. Dies bedeutet auch, dass die Information im Control File gespeichert wird. Daher ist es sinnvoll direkt nach em Umsetzen des Modus ein Backup vom Controlfile zu erstellen.
SQL> startup mount;

SQL> alter database force full database caching;

Database altered.

-- Ausschalten mit
-- ALTER DATABASE NO FORCE FULL DATABASE CACHING;

SQL> SELECT force_full_db_caching FROM v$database;

FOR
---
YES
Die Information über den Full Database Caching Mode der Datenbank lässt sich dann auch in der Alert Datei nachlesen.
Completed: ALTER DATABASE   MOUNT
2015-12-15 02:56:03.396000 -08:00
alter database force full database caching
Completed: alter database force full database caching
Um Missverständnisse zu vermeiden: Nach der Konfiguration einer Datenbank im Force Full Database Mode werden nicht automatisch alle Objekte in den Cache verlagert. Es muss zuerst ein Zugriff auf die Objekte erfolgen. Überprüfen wir unsere Umgebung und betrachten wir dabei die Objekte des Users SCOTT. Ohne Zugriffe sind keine Objekte im Cache zu verzeichnen.
col object_name format a20
col object_type format a20
col owner format a20
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 owner = 'SCOTT'
     GROUP BY o.object_name, o.owner, o.object_type
     ORDER BY COUNT(*);
no rows selected
Folgende Objekte stehen übrigens im Schema SCOTT zur Verfügung.
SQL> select segment_name, segment_type from dba_segments 
     where owner='SCOTT' group by segment_name, segment_type;  

SEGMENT_NAME		       SEGMENT_TYPE
------------------------------ ------------------
SYS_IL0000019874C00010$$       LOBINDEX
EMP			       TABLE
SYS_LOB0000019874C00010$$      LOBSEGMENT
DEPT			       TABLE
TEST_LOB		       TABLE
SALGRADE		       TABLE
PK_DEPT 		       INDEX
PK_EMP			       INDEX

8 rows selected.
Die Tabelle TEST_LOB besitzt eine LOB Spalte, die standardmässig nicht für den Cache vorgesehen ist. Um die Funktion des Force Full Database Caching Mode zu demonstrieren, werden nun Zugriffe auf das Lobsegment in zwei verschiedenen Umgebungen (mit und ohne Force Full Database Caching) durchgeführt.
SQL> select segment_name, securefile, cache 
     from dba_lobs where owner='SCOTT';

SEGMENT_NAME				 SEC CACHE
---------------------------------------- --- ----------
SYS_LOB0000019874C00010$$		 YES NO
Nun greifen wir mehrfach auf das Objekt TEST_LOB zu. Wie zu erwarten war, sind in der aktuellen Umgebung mit Force Full Database Caching keine Physical Reads zu verzeichnen. Offensichtlich ist auch das LOB Segment im Cache, obwohl es standardmässig als NO CACHE angelegt wird (siehe oben).
SQL> select * from scott.test_lob

80 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 825212230

------------------------------------------------------------------------------
| Id  | Operation	  | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	     |	  80 |	 108K|	   7   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| TEST_LOB |	  80 |	 108K|	   7   (0)| 00:00:01 |
------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	  0  recursive calls
	  0  db block gets
	189  consistent gets
	  0  physical reads
	  0  redo size
      51589  bytes sent via SQL*Net to client
      21991  bytes received via SQL*Net from client
	162  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
	 80  rows processed
Auch die Überprüfung der V$BH View bestätigt das Ergebnis.
col object_name format a20
col object_type format a20
col owner format a20
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 owner = 'SCOTT'
GROUP BY o.object_name, o.owner, o.object_type
ORDER BY COUNT(*);

OBJECT_NAME	     OBJECT_TYPE	  OWNER 	       NUMBER_OF_BLOCKS
-------------------- -------------------- -------------------- ----------------
PK_EMP		     INDEX		  SCOTT 			      2
PK_DEPT 	     INDEX		  SCOTT 			      2
DEPT		     TABLE		  SCOTT 			      9
EMP		     TABLE		  SCOTT 			      9
SALGRADE	     TABLE		  SCOTT 			      9
TEST_LOB	     TABLE		  SCOTT 			     26
SYS_LOB0000019874C00 LOB		  SCOTT 			     28
010$$
Nun vergleichen wir dieses Ergebnis mit dem Verhalten im Default Database Caching Mode. Dazu fahren wir die Datenbank herunter und schalten im MOUNT Stadium der Datenbank den No Force Full Database Caching Mode ein. Danach öffnen wir die Datenbank und wiederholen die gleiche Abfrage in der geänderten Umgebung.
SQL> select * from scott.test_lob

80 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 825212230

------------------------------------------------------------------------------
| Id  | Operation	  | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |	     |	  80 |	 166K|	   7   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| TEST_LOB |	  80 |	 166K|	   7   (0)| 00:00:01 |
------------------------------------------------------------------------------

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)


Statistics
----------------------------------------------------------
	  0  recursive calls
	  0  db block gets
	165  consistent gets
	 24  physical reads
	  0  redo size
      51589  bytes sent via SQL*Net to client
      21991  bytes received via SQL*Net from client
	162  SQL*Net roundtrips to/from client
	  0  sorts (memory)
	  0  sorts (disk)
	 80  rows processed
Der gleiche Zugriff auf das Segment weist nun Physical Reads auf.

Häufig wird die Frage gestellt, was passiert, wenn die Datenbank wächst und die Speicherplatzanforderungen den Buffer Cache übersteigen? Wichtig zu wissen ist: Der Modus wird nicht automatisch umgeschaltet. Man wird wieder Physical Reads feststellen. Allerdings wird eine Information in der Alert Datei wie folgt notiert:
Thread 1 opened at log sequence 44
  Current log# 2 seq# 44 mem# 0: /home/oracle/app/oracle/oradata/test/redo02.log
Successful open of redo thread 1
Fri Dec 18 02:20:54 2015
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set
Buffer Cache Force Full DB Caching mode on when DB does not fit  in cache. 
   Turning off Force Full DB Caching advisable
Fazit

Force Full Database Caching eignet sich hervorragend für kleine Datenbanken, deren genutzter Speicherplatz in den Buffer Cache passt. So kann man sehr einfach, die Datenbank Performance von Full Table Scans und Zugriffen auf Large Objects erhöhen. Keine Änderungen an den Abfragen oder Segmenten ist dazu erforderlich. Nicht verwechseln sollte man diese Funktion mit der Oracle Database In-Memory Option, die viel weiter geht. Sie zeichnet sich durch eine neue Form der Cache Ablage aus - nämlich Spalten basiert und zusätzlich komprimiert - und profitiert zusätzlich von speziellen optimierten Statementzugriffen. Mit dieser Technik können ausserordentliche Performancegewinne erzielt werden, wie uns einige Kunden schon nach einer ersten Testphase bestätigen konnten.

Bevor man diese Funktion verwendet, sollte man allerdings sicherstellen, dass ausreichend Memory vorhanden ist. Für RAC Umgebungen bedeutet dies, dass der aktuell genutzte Datenbankspeicherplatz kleiner als der jeweilige (individuelle) Buffer Cache jeder Datenbank Instance ist. Ist der Workload in der RAC Umgebung ausreichend gut partitioniert (bzgl. Instance Zugriff), kann der aktuell genutzte Datenbankspeicherplatz auch kleiner als 80% des kombinierten Buffer Caches sein.

Zurück zur Community-Seite