Oracle
 sql >> Database >  >> RDS >> Oracle

Considerazioni sulle prestazioni per i dati temporanei in Oracle

Le tabelle temporanee sono effettivamente le stesse delle tabelle in memoria grazie alla memorizzazione nella cache e all'I/O asincrono e la soluzione delle tabelle temporanee non richiede alcun sovraccarico per la conversione tra SQL e PL/SQL.

Conferma dei risultati

Confrontando le due versioni con RunStats, la versione della tabella temporanea sembra molto peggio. Tutta quella spazzatura per la versione della tabella temporanea in Run1 e solo un po' di memoria extra per la versione PL/SQL in Run2. All'inizio sembra che PL/SQL dovrebbe essere il chiaro vincitore.

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

Ma alla fine della giornata conta solo l'ora dell'orologio da parete. Sia il caricamento che i passaggi di query vengono eseguiti molto più velocemente con le tabelle temporanee.

La versione PL/SQL può essere migliorata sostituendo BULK COLLECT con cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t . Ma è ancora significativamente più lento della versione con tabella temporanea.

Letture ottimizzate

La lettura dalla piccola tabella temporanea utilizza solo la cache del buffer, che è in memoria. Esegui molte volte solo la parte della query e osserva come il consistent gets from cache (memoria) aumenta mentre la physical reads cache (disco) rimane lo stesso.

select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache', 
'physical reads cache');

Scritture ottimizzate

Idealmente non ci sarebbe I/O fisico, soprattutto perché la tabella temporanea è ON COMMIT DELETE ROWS . E sembra che la prossima versione di Oracle possa introdurre un tale meccanismo. Ma non importa molto in questo caso, l'I/O del disco non sembra rallentare le cose.

Esegui il passaggio di caricamento più volte, quindi esegui select * from v$active_session_history order by sample_time desc; . La maggior parte dell'I/O è BACKGROUND , il che significa che nulla lo sta aspettando. Presumo che la logica interna della tabella temporanea sia solo una copia dei normali meccanismi DML. In generale, i nuovi dati della tabella possono deve essere scritto su disco, se è stato eseguito il commit. Oracle potrebbe iniziare a lavorarci, ad esempio spostando i dati dal buffer di registro al disco, ma non c'è fretta finché non si verifica un vero COMMIT .

Dove va il tempo PL/SQL?

Non ho idea. Esistono più cambi di contesto o un'unica conversione tra i motori SQL e PL/SQL? Per quanto ne so, nessuna delle metriche disponibili mostra il tempo speso per passare da SQL a PL/SQL.

Potremmo non sapere mai esattamente perché il codice PL/SQL è più lento. Non me ne preoccupo troppo. La risposta generale è che la stragrande maggioranza del lavoro sul database deve comunque essere eseguita in SQL. Avrebbe molto senso se Oracle dedicasse più tempo all'ottimizzazione del core del proprio database, SQL, rispetto al linguaggio aggiuntivo, PL/SQL.

Note aggiuntive

Per i test delle prestazioni può essere utile rimuovere connect by logica in un passaggio separato. Quell'SQL è un ottimo trucco per caricare i dati, ma può essere molto lento e dispendioso in termini di risorse. È più realistico caricare una tabella di esempio una volta con quel trucco, quindi inserirla da quella tabella.

Ho provato a utilizzare la nuova funzionalità Oracle 12c, annullamento temporaneo e la nuova funzionalità 18c, tabelle temporanee private. Nessuno dei due ha migliorato le prestazioni rispetto alle normali tabelle temporanee.

Non ci scommetterei, ma posso vedere un modo in cui i risultati cambierebbero completamente man mano che i dati diventano più grandi. Il buffer di registro e la cache del buffer possono solo diventare così grandi. E alla fine quell'I/O in background potrebbe sommarsi e sovraccaricare alcuni processi, trasformando il BACKGROUND attendi in un FOREGROUND aspettare. D'altra parte, c'è solo così tanta memoria PGA per la soluzione PL/SQL e poi le cose vanno in crash.

Infine, ciò conferma in parte il mio scetticismo nei confronti dei "database in memoria". La memorizzazione nella cache non è una novità, i database lo fanno da decenni.