Tijdelijke tabellen zijn in feite hetzelfde als in-memory tabellen dankzij caching en asynchrone I/O, en de tijdelijke tabeloplossing vereist geen overhead voor het converteren tussen SQL en PL/SQL.
De resultaten bevestigen
Als we de twee versies vergelijken met RunStats, ziet de tijdelijke tabelversie er uit veel slechter. Al die rommel voor de tijdelijke tabelversie in Run1 en slechts een beetje extra geheugen voor de PL/SQL-versie in Run2. In eerste instantie lijkt het erop dat PL/SQL de duidelijke winnaar zou moeten zijn.
Type Name Run1 (temp) Run2 (PLSQL) Diff
----- -------------------------------- ------------ ------------ ------------
...
STAT physical read bytes 81,920 0 -81,920
STAT physical read total bytes 81,920 0 -81,920
LATCH cache buffers chains 104,663 462 -104,201
STAT session uga memory 445,488 681,016 235,528
STAT KTFB alloc space (block) 2,097,152 0 -2,097,152
STAT undo change vector size 2,350,188 0 -2,350,188
STAT redo size 2,804,516 0 -2,804,516
STAT temp space allocated (bytes) 12,582,912 0 -12,582,912
STAT table scan rows gotten 15,499,845 0 -15,499,845
STAT session pga memory 196,608 19,857,408 19,660,800
STAT logical read bytes from cache 299,958,272 0 -299,958,272
Maar aan het eind van de dag is alleen de tijd van de wandklok van belang. Zowel het laden als het opvragen verloopt veel sneller met tijdelijke tabellen.
De PL/SQL-versie kan worden verbeterd door de BULK COLLECT
te vervangen met cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t
. Maar het is nog steeds aanzienlijk langzamer dan de tijdelijke tabelversie.
Geoptimaliseerde leesbewerkingen
Lezen uit de kleine tijdelijke tabel gebruikt alleen de buffercache, die zich in het geheugen bevindt. Voer alleen het querygedeelte vaak uit en kijk hoe de consistent gets from cache
komt (geheugen) toenemen terwijl de physical reads cache
(schijf) hetzelfde blijven.
select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache',
'physical reads cache');
Geoptimaliseerde schrijfbewerkingen
Idealiter zou er geen fysieke I/O zijn, vooral omdat de tijdelijke tabel ON COMMIT DELETE ROWS
is . En het klinkt alsof de volgende versie van Oracle een dergelijk mechanisme zou kunnen introduceren. Maar in dit geval maakt het niet veel uit, de schijf-I/O lijkt de dingen niet te vertragen.
Voer de laadstap meerdere keren uit en voer vervolgens select * from v$active_session_history order by sample_time desc;
. Het grootste deel van de I/O is BACKGROUND
, wat betekent dat er niets op wacht. Ik neem aan dat de interne logica van de tijdelijke tabel slechts een kopie is van reguliere DML-mechanismen. Over het algemeen kunnen nieuwe tabelgegevens mogelijk moeten naar schijf worden geschreven, als het is vastgelegd. Oracle kan eraan gaan werken, bijvoorbeeld door gegevens van de logbuffer naar schijf te verplaatsen, maar er is geen haast totdat er een daadwerkelijke COMMIT
is .
Waar gaat de PL/SQL-tijd naartoe?
Ik heb geen idee. Zijn er meerdere context-switches, of een enkele conversie tussen de SQL- en PL/SQL-engines? Voor zover ik weet, geeft geen van de beschikbare statistieken de tijd . weer besteed aan het schakelen tussen SQL en PL/SQL.
We zullen misschien nooit precies weten waarom PL/SQL-code langzamer is. Ik maak me er niet al te veel zorgen over. Het algemene antwoord is dat het overgrote deel van het databasewerk sowieso in SQL moet worden gedaan. Het zou heel logisch zijn als Oracle meer tijd zou besteden aan het optimaliseren van de kern van hun database, SQL, dan aan de add-on-taal PL/SQL.
Aanvullende opmerkingen
Voor prestatietests kan het handig zijn om de connect by
. te verwijderen logica in een aparte stap. Die SQL is een geweldige truc voor het laden van gegevens, maar het kan erg traag en arbeidsintensief zijn. Het is realistischer om een voorbeeldtabel één keer met die truc te laden en vervolgens vanuit die tabel in te voegen.
Ik heb geprobeerd de nieuwe Oracle 12c-functie, tijdelijk ongedaan maken, en de nieuwe 18c-functie, tijdelijke privétabellen te gebruiken. Geen van beide verbeterde de prestaties ten opzichte van gewone tijdelijke tafels.
Ik zou er niet op wedden, maar ik zie een manier waarop de resultaten volledig zouden veranderen naarmate de gegevens groter worden. De logbuffer en de buffercache kunnen alleen zo groot worden. En uiteindelijk zou die achtergrond-I/O kunnen oplopen en sommige processen overweldigen, waardoor de BACKGROUND
wacht in een FOREGROUND
wacht. Aan de andere kant is er maar zoveel PGA-geheugen voor de PL/SQL-oplossing, en dan crasht het.
Ten slotte bevestigt dit gedeeltelijk mijn scepsis over "in-memory databases". Caching is niets nieuws, databases doen het al tientallen jaren.