Oracle 11.2, le hint APPEND_VALUES

Une petite polémique avait débuté avec le hint APPEND et Oracle 11.1. En effet Oracle avait alors modifié son fonctionnement pour supporter le hint avec la clause VALUES d’un ordre INSERT. Depuis, ils sont, sans doute, revenus en arrière. Personnellement je trouvais l’idée très séduisante et j’ai d’ailleurs écrit plusieurs articles à ce sujet puisque ça ouvrait la porte à l’écriture de programmes Pro*C, OCI ou PL/SQL qui pouvaient intégrer des données de manière massive, sans logs et sans insert as select ni tables externes.
D’autres, sans doute plus pragmatiques, mettaient en avant que si un programme fonctionnait en 10g et qu’un développeur avait par mégarde ajouté ce hint à un insert ... values, la table serait lockée en mode exclusif le temps de la transaction associée et le High Water Mark déplacé, même pour une ligne. Les conséquences d’une mauvaise utilisation pouvaient donc être catastrophiques. J’avoue que, dans une première approche au moins, punir les gens qui utilisent des hints sans savoir pourquoi ne faisait qu’ajouter à mon plaisir… Enfin, on peut imaginer des situations assez compliquées pour migrer en 11g. Malheureux ceux qui n’auraient pas testé !
Oracle 11.2 coupe donc la poire en 2 en intégrant la fonctionnalité du hint APPEND avec une clause VALUES mais en changeant le nom du hint pour tous les mauvais développeurs ne soient pas punis malgré tout. Dans cet article, je reprends l’exemple que j’avais écrit à l’époque et qui est toujours disponible sur mon ancien blog mais en changeant les hints utilisés.

Note:
Le numéro et le nom de la statisque ont également changé en 11.2; j’ai donc modifié l’exemple en conséquence.

Tests avec les Hints APPEND_VALUES et APPEND

Le script ci-dessous crée un schéma et une table d’exemple; il calcule le nombre de blocs écrits en mode directs avec les hints APPEND et APPEND_VALUES :

create user demo
   identified by demo
   default tablespace users
   temporary tablespace temp;
grant connect, resource to demo;
grant select on sys.v_$mystat to demo;
grant select on sys.v_$statname to demo;
connect demo/demo
define myhint = "append_values"
prompt &&myhint
create table insertappend
  (id number,
   text varchar2(200));
set serveroutput on
declare
  id dbms_utility.number_array;
  text dbms_utility.lname_array;
  dpw number;
begin
   select m.value into dpw
     from v$mystat m, v$statname s
    where s.statistic#=m.statistic#
      and s.name='physical writes direct';
   for i in 1..10000 loop
      id(i)   := i;
      text(i) := to_char(i);
   end loop;
   forall i in 1..10000
      insert /*+ &&myhint */
         into insertappend(id,text)
         values (id(i),text(i));
    select m.value-dpw into dpw
     from v$mystat m, v$statname s
    where s.statistic#=m.statistic#
      and s.name='physical writes direct';
    dbms_output.put_line(
       '"Physical Write Direct" avec le Hint &&myhint : '
       ||to_char(dpw));
end;
/

Le résultat est le suivant sur mon laptop :

"Physical Write Direct" avec le Hint append_values : 20

Vous pouvez effectuer la même opération avec le Hint APPEND; Il n’y a pas d’écritures en mode direct en 11.2:

define myhint = "append"
prompt &&myhint
/
"Physical Write Direct" avec le Hint append : 0

Convaincu? Vous pouvez supprimer la table et l’utilisateur :

drop table demo.insertappend purge;
drop user demo cascade;

Et restez dans les environs, il y a encore beaucoup de nouvelles fonctionnalités que nous allons explorer dans les jours qui viennent….