Hoe verbeter je de performance van Object Types in Oracle

Erik Sekeris – Oracle is een RDBMS, een Relationeel Data Base Management Systeem. Dus, zoals de naam al zegt, sterk gericht op Relationele data. Toch wordt de Oracle database al jaren ingezet voor (bijvoorbeeld) Java applicaties. Een Object Oriented taal tegen een Relationele database. Dat kan wel eens voor problemen zorgen.

Een specifiek probleem wat ik vaak zie terugkeren is het gebruik van Object Types in Oracle, en dan met name als het om Nested Tables gaat.

Object Types in Oracle

Object Types

Binnen Oracle kun je (heel makkelijk) een eigen gedefinieerd object aanmaken. Zo’n object bundelt bij elkaar horende attributen en kan zelf als attribuut in een (relationele) tabel worden opgenomen. Deze Object Types kun je weer bundelen tot een Table Type, een verzameling voor soortgelijke objecten die weer als object/attribuut bij elkaar horen.

Table Types

Wat is dan zo’n Table Type? Een eenvoudig voorbeeld haal ik even uit de transportwereld. Stel je een (goederen)trein voor met verschillende wagons. Deze wagons bevatten op hun beurt weer lading. Een simpel Object model zou dan zijn dat je een Object Lading definieert (met een paar specifieke attributen), dat je Wagons definieert die meerdere Objecten van Lading kan bevatten en dat een Trein meerdere Objecten van Wagon kan bevatten.

Dit kun je uiteraard relationeel opslaan, maar een Java applicatie houdt er van om dit als objecten binnen te krijgen. Als je dus al een Trein kan ophalen met daarbinnen al gelijk meerdere Wagons en daar weer binnen meerdere Ladingen, kun je in Java gelijk aan de slag, zonder eerst een conversie uit te voeren. De Wagons en ladingen sla je dan als Table Type op bij de Trein.

Nested Tables

Een Nested Table is een tabel binnen een tabel in Oracle. Je slaat als het ware in de hoofdtabel per regel een tabel op waarin je de details van het object vastlegt. Terug naar het voorbeeld van de Trein, zou je een trein als relationeel record kunnen opslaan en bij die trein (in dezelfde tabel) alle bijbehorende Wagons als Table Type. De Wagons (en daarbinnen hun Ladingen) worden dan onderdeel van het Trein Object op het moment dat je hem in de applicatie nodig hebt.

Let wel: dit werkt alleen zolang je al deze gegevens als één Object nodig hebt. Het wordt namelijk erg vervelend om bijvoorbeeld losse wagons op te gaan zoeken, want een wagon hoort nu direct bij één trein. Maar voor het voorbeeld willen we een trein altijd in zijn geheel behandelen.

Het probleem

Door de records als Nested Table op te slaan maakt Oracle zelf voor alle Objecten en sub-Objecten eigen tabellen aan. Oracle zelf vertaalt dus het Object model naar een Relationeel model.

Dit gaat prima, maar met grote aantallen records wordt dit in de praktijk soms erg traag. Standaard zal Oracle namelijk voor alle records uit de hoofdtabel een volledige scan doen op alle gegenereerde tabellen. En als het veel records zijn met veel detail-objecten die ook nog eens zeer vertakt zijn, levert dit heel veel load op het systeem.

Ik heb systemen gezien waarin er 14 verschillende objecten tot 5 lagen diep met diverse vertakkingen waren aangemaakt. En voor ieder op te halen record doorliep de database alle miljoenen instanties van de Nested Tables.

De oplossing

Waarom gaat dit dan mis? Waarom doet Oracle hier niets aan?

Dat Oracle er niets aan zou doen is niet zozeer het probleem, maar vaak wordt vergeten om de door Oracle aangegeven ”best practices” te volgen. Het is heel makkelijk een Nested Table aan te maken. Het is echter ook heel makkelijk te vergeten daar de juiste opties bij te zetten.

In de “Oracle® Database Object-Relational Developer's Guide” staan die richtlijnen wel, maar worden dus vaak vergeten. Het komt er op neer dat je twee opties hebt:

Sla de Nested Table op als een IOT (Index Organized Table), dan is de performance automatisch goed. Dit is de door Oracle aanbevolen manier.
Of, maak na het aanmaken van de Nested Table op iedere (sub)tabel een eigen index aan op de NESTED_TABLE_ID kolom, waarmee Oracle ook de juiste objecten bij het hoofdrecord kan vinden. Werkt in de praktijk net zo goed als een IOT, maar heeft wat meer administratief werk.

Beide opties zorgen voor een dramatische verbetering in de performance. Op die manier wordt het toch |(weer) interessant om Object Types te gaan gebruiken binnen Oracle.

Meer weten?

Om de leesbaarheid te verhogen bevat deze versimpelde weergave nog niet de technische details en nuances. Uiteraard helpen wij graag verder met het inrichten en optimaliseren van deze en andere structuren.

Stuur voor vragen een e-mail naar: Wim Stolk of bel via T: +31 886 606 600