Les tables temporaires sont effectivement les mêmes que les tables en mémoire grâce à la mise en cache et aux E/S asynchrones, et la solution de table temporaire ne nécessite aucune surcharge pour la conversion entre SQL et PL/SQL.
Confirmation des résultats
En comparant les deux versions avec RunStats, la version de la table temporaire regarde bien pire. Tout ce bazar pour la version de la table temporaire dans Run1, et seulement un peu de mémoire supplémentaire pour la version PL/SQL dans Run2. Au début, il semble que PL/SQL devrait être le grand gagnant.
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
Mais en fin de compte, seule l'heure de l'horloge murale compte. Les étapes de chargement et d'interrogation s'exécutent beaucoup plus rapidement avec les tables temporaires.
La version PL/SQL peut être améliorée en remplaçant le BULK COLLECT
avec cast(collect(test_o(MOD(a, 10), '' || MOD(a, 12))) as test_t) INTO t
. Mais c'est toujours beaucoup plus lent que la version de la table temporaire.
Lectures optimisées
La lecture de la petite table temporaire n'utilise que le tampon cache, qui est en mémoire. Exécutez uniquement la partie requête plusieurs fois et observez comment le consistent gets from cache
(mémoire) augmente pendant que le physical reads cache
(disque) reste le même.
select name, value
from v$sysstat
where name in ('db block gets from cache', 'consistent gets from cache',
'physical reads cache');
Écritures optimisées
Idéalement, il n'y aurait pas d'E/S physiques, d'autant plus que la table temporaire est ON COMMIT DELETE ROWS
. Et il semble que la prochaine version d'Oracle puisse introduire un tel mécanisme. Mais peu importe dans ce cas, les E/S disque ne semblent pas ralentir les choses.
Exécutez l'étape de chargement plusieurs fois, puis exécutez select * from v$active_session_history order by sample_time desc;
. La plupart des E/S sont BACKGROUND
, ce qui signifie que rien ne l'attend. Je suppose que la logique interne de la table temporaire n'est qu'une copie des mécanismes DML habituels. En général, les nouvelles données de table peuvent doivent être écrites sur le disque, si elles sont validées. Oracle peut commencer à travailler dessus, par exemple en déplaçant les données du tampon de journal vers le disque, mais il n'y a pas d'urgence tant qu'il n'y a pas de véritable COMMIT
.
Où va le temps PL/SQL ?
Je n'ai aucune idée. Existe-t-il plusieurs changements de contexte ou une seule conversion entre les moteurs SQL et PL/SQL ? Autant que je sache, aucune des mesures disponibles n'indique le temps dépensé pour basculer entre SQL et PL/SQL.
Nous ne saurons peut-être jamais exactement pourquoi le code PL/SQL est plus lent. Je ne m'en soucie pas trop. La réponse générale est que la grande majorité du travail de base de données doit de toute façon être effectuée en SQL. Cela aurait beaucoup de sens si Oracle passait plus de temps à optimiser le cœur de sa base de données, SQL, que le langage complémentaire, PL/SQL.
Remarques supplémentaires
Pour les tests de performances, il peut être utile de supprimer le connect by
logique dans une étape distincte. Ce SQL est une excellente astuce pour charger des données, mais il peut être très lent et gourmand en ressources. Il est plus réaliste de charger un exemple de table une fois avec cette astuce, puis de l'insérer à partir de cette table.
J'ai essayé d'utiliser la nouvelle fonctionnalité Oracle 12c, l'annulation temporaire, et la nouvelle fonctionnalité 18c, les tables temporaires privées. Aucune des deux n'a amélioré les performances par rapport aux tables temporaires classiques.
Je ne parierais pas là-dessus, mais je peux voir comment les résultats changeraient complètement à mesure que les données augmenteraient. Le tampon de journal et le cache de tampon ne peuvent devenir volumineux. Et éventuellement, ces E/S en arrière-plan pourraient s'additionner et submerger certains processus, transformant le BACKGROUND
attendre dans un FOREGROUND
Attendez. D'un autre côté, il n'y a pas assez de mémoire PGA pour la solution PL/SQL, et puis les choses plantent.
Enfin, cela confirme en partie mon scepticisme à l'égard des "bases de données en mémoire". La mise en cache n'a rien de nouveau, les bases de données le font depuis des décennies.