Database performance tuning
5 feb 2012 - Frits Hoogland

Verschenen in OGh Visie voorjaar 2012
Niets is zo uitvoerig beschreven en met zoveel mystiek omgeven als performance tuning. En om eerlijk te zijn: er zijn veel componenten/lagen die invloed hebben op performance, waardoor het goed mogelijk is ‘overdonderd’ te raken door details.
Database performance tuning

Wat is performance?

Het is goed eerst eens stil te staan bij de definitie. Performance is in de meeste gevallen waarschijnlijk niet de beste omschrijving. ‘Response time’ is een meer accurate omschrijving. Terwijl met ‘performance’ het geheel van applicatie, database, servers, et cetera wordt aangeduid, neigt ‘response time’ naar ‘iets’ te wijzen. Dat is exact het tweede punt om naar te kijken:

 

Welke Performance?

De eerste stap is hier weer te spreken over ‘response time’. De volgende stap: welke response time? Laten we bij deze vraag eens een vereenvoudigde, schematische tekening bekijken van een typische webapplicatie:

Figuur 1

 

Figuur 1 laat een request zien van een client naar een applicatieserver die maar 1 ‘roundtrip’ (1 antwoord op 1 vraag) doet. In vrijwel alle situaties is dit niet het geval.

->          De response times van de lagen (alle ‘rn’) in dit voorbeeld zijn volkomen willekeurig  en niet representatief. Voor het toepassen van deze technieken moeten deze       gemeten worden voor die specifieke situatie!

r1 is de tijd die de end-user ervaart. Als er klachten komen over performance, is deze gebaseerd op de tijd in r1, van een specifieke request. Dit is dus ‘end-user performance’.

r1a is de zogenaamde ‘time of flight’, de tijd die het kost om de browser request naar de applicatieserver te transporteren. Dit zal in veel gevallen (vooral voor applicaties in een lokaal netwerk) verwaarloosbaar zijn. Een request over het internet kan potentieel een langere ‘time of flight’ hebben. Het is belangrijk stil te staan bij het bestaan van deze component in de response time, die significante proporties kan aannemen als er intensief over het netwerk gecommuniceerd wordt voor de uitvoering van een request.

r2 is de response time van de applicatieserver. Dit is de tijd die de applicatieserver nodig heeft om een request te ontvangen, te verwerken, uit te voeren en het antwoord terug te sturen. Dit is dus applicatieserver performance’.

r3 en r5 zijn database acties veroorzaakt door aanroepen van de applicatieserver. Voor de database geldt hetzelfde als voor de applicatieserver: r3 en r5 zijn beide de tijd die nodig is om de request te ontvangen, te verwerken, uit te voeren en het antwoord terug te sturen. Dit is dus ‘database performance’.

r4 is de response time van een IO request die wordt geserveerd door een fysieke disk in de database server, of een SAN of NAS.

Laten we nu terug komen bij de vraag ‘welke performance’: een gebruikers-performance klacht gaat over r1. Welke tijd ga je als performance tuner gebruiken voor het oplossen van het performance probleem?

 

Wat is goede performance?

De volgende stap in het oplossen van een probleem is het overeenkomen van een meetpunt voor de response time, en een doel tijd. Dit betekent dat een performance probleem reproduceerbaar moet zijn. Je kan niet iets meten als het er niet is, of er niet meer is. Het is belangrijk op te merken dat ik zeer weinig tegenkom dat een doel tijd voor de response tijd wordt gesteld en overeengekomen. ‘Het moet performen’ is meestal het doel.

 

Hoe te tunen

Effectief tunen begint met definiëren van een reproduceerbaar response time probleem. Dit kan zijn een bepaald scherm of bepaalde handeling in een webapplicatie, maar ook bijvoorbeeld een script die een batch uitvoert.

De volgende stap is een zo goed mogelijk meetpunt definieren. Voor een webapplicatie kan je hiervoor gebruik maken van tools als ‘firebug’ (Firefox), ‘web inspector’ (Safari/Mac OSX) of ‘httpwatch’ (IE). Voor batches geldt vaak dat om inzicht te krijgen in response time wat extra code ‘om de batch’ gemaakt moet worden die de tijd voor en na de hele batch of onderdelen van de batch in de logfile of logfiles neerzet. Dit toevoegen van code om inzicht te krijgen in de response time karakteristieken heet ‘instrumentatie’. Op basis van de tijd in het meetpunt moet een tijd overeengekomen worden dat het performance probleem als ‘opgelost’ wordt beschouwd.

Ik ben mij er van bewust dat dit een hele simpele weergave van de werkelijkheid is. In een dergelijk traject is het zeer goed mogelijk dat de tuning-stappen een aantal malen herhaald moeten worden voordat het probleem als geheel ‘goed performt’, dus een acceptabele response time heeft. Ook is het goed mogelijk dat een laag een ‘black box’ kan zijn (bijvoorbeeld gekochte applicatie), waarbij allerlei metingen minder of niet mogelijk zijn.

 

Na deze stap zijn dus twee cruciale zaken bekend:

a)   Wat te meten.

b)  Wat voor response time dit minimaal moet hebben; ‘response time target’.

De volgende stap is de response time ‘compositie’ te bepalen. De compositie is hoe de response time als geheel is opgebouwd. Laten we eens kijken naar de compositie van bovenstaande voorbeeld:

 

Figuur 2

 

Het is belangrijk stil te staan hoe de verschillende lagen elkaar beïnvloeden. r1 is de totale response time. r1 is opgebouwd uit r2 (95%) en r1a (de onderste 5%, niet vermeld in figuur 2). Elke diepere laag beïnvloed de bovenliggende lagen, en niet de onderliggende lagen.

Een aanpassing in r4 (de disk request van r3) leidt tot aanpassing van r3, als gevolg daarvan van leidt dit tot een aanpassing van r2 (r3 is de database request van r2), en als gevolg daarvan tot een aanpassing van r1. Of heel concreet: als de database actie r3 geen disk IO (r4) doet, nemen r3,r2, r1 af met de response time van r4 (5%).

Andersom: als r2 (de applicatie server response time) wordt verminderd door een aanpassing die geen invloed heeft op de onderliggende lagen (de database calls r3 en r5 in dit geval), dan neemt r2 af, r1 ook, omdat die gebaseerd is op r2, maar niet op r3,r4 en r5.

Op basis van figuur 2 kan een een aantal belangrijke constateringen worden gedaan:

  1. Het versnellen van de disks of van het SAN zonder iets anders aan te passen zal tot maximaal 5% verbetering leiden in dit geval, in het onmogelijke geval dat disk IO tijd 0 wordt, wat natuurlijk niet reëel is.
  2. Het optimaliseren van de database kan maximaal tot 33% response time reductie leiden.
  3. Het optimaliseren van de applicatie op de applicatieserver kan tot 95% response time reductie leiden.

Dit klinkt natuurlijk leuk, maar het is in de praktijk moeilijk al deze zaken te meten en daarmee de compositie compleet te krijgen. Dus: hoe ga je dit in de praktijk nu doen?

Het is noodzakelijk een totale response time meting te hebben en een response time target. Zonder deze twee is het niet mogelijk impact of verbetering te bepalen en niet mogelijk te bepalen wanneer het goed is.

Dit beteken dat 100% bekend is. In de meeste gevallen die ik tegenkom, is de applicatie op de applicatieserver niet uitgerust met de mogelijkheid om een individuele request te identificeren en de compositie van dit request te bepalen. De Oracle database is echter uitstekend uitgerust om database requests te meten en de compositie van de response time in de database weer te geven.

 

Door de lagen van een web applicatie te groeperen tot de algemene hoofdzaken kom je tot:

   Browser -> Applicatie Server -> Database

Als je aan de hand van dit model de metingen invult, namelijk 100% voor ‘browser’ en daarna de tijd of het tijdsaandeel van de database uit de databasemeting, zie je dat voor het bepalen van het aandeel in de response time van deze groepsindeling de applicatie server meting niet nodig is:

Browser -> Applicatie Server -> Database
100%             X%               33%

Het mag duidelijk zijn dat X hier 67% moet zijn. In dit model is netwerk latency achterwege gelaten.

Aan de hand van deze metingen en het response time target kan bepaald worden op welk onderdeel je je vervolgens gaat richten voor verbetering. Als het doel is tot 50% response time verbetering te komen, zal alleen het aanpassen/tunen van de database niet volstaan, omdat deze slechts een aandeel heeft van 33%.