Sur une base de données 11gR2 avec cette configuration
SHOW PARAMETER DISK_ASYNCH_IO
NAME TYPE VALUE
------------------------ ----------- ------
disk_asynch_io boolean TRUE
SHOW PARAMETER FILESYSTEMIO_OPTIONS
NAME TYPE VALUE
------------------------ ----------- ------
filesystemio_options string asynch
SHOW PARAMETER PARALLEL_SERVERS_TARGET
NAME TYPE VALUE
------------------------ ----------- ------
parallel_servers_target integer 256
SHOW PARAMETER PARALLEL_MAX_SERVERS
NAME TYPE VALUE
------------------------ ----------- ------
parallel_max_servers integer 640
SHOW PARAMETER PARALLEL_DEGREE_POLICY
NAME TYPE VALUE
------------------------ ----------- ------
parallel_degree_policy string MANUAL
Ici on a quelque chose à considérer avant notre essai, c'est important d'avoir les statistiques sur le I/O que dans mon cas sur cette Bd ne sont pas disponibles :
SELECT * FROM V$IO_CALIBRATION_STATUS;
STATUS CALIBRATION_TIME
------------- ----------------------------------------
NOT AVAILABLE
SET SERVEROUTPUT ON
DECLARE
lat INTEGER;
iops INTEGER;
mbps INTEGER;
BEGIN
DBMS_RESOURCE_MANAGER.CALIBRATE_IO (2, 10, iops, mbps, lat);
DBMS_OUTPUT.PUT_LINE ('max_iops = ' || iops);
DBMS_OUTPUT.PUT_LINE ('latency = ' || lat);
DBMS_OUTPUT.PUT_LINE ('max_mbps = ' || mbps);
end;
/
max_iops = 669
latency = 8
max_mbps = 1357
PL/SQL procedure successfully completed.
Dans mes essais j'ai eu toujours le même résultat avec un hint PARALLEL ou APPEND.
Table sans une PK :
Donc, on va recommencer avec une table mais sans PK :
CREATE TABLE PERE (ID NUMBER, STRNG VARCHAR2 (30)) ;
ALTER SESSION FORCE PARALLEL DML;
INSERT /*+ PARALLEL */ INTO PERE
SELECT 1 + (Level -1) * 1 AS ID, TO_CHAR(1 + (Level -1) * 1)||'_MYTEST' CHAINE
FROM DUAL CONNECT BY LEVEL <= 100 ;
COMMIT ;
Maintenant on va regarder la trace :
STAT #18446744071472298536 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=3 pr=0 pw=0 time=123689 us)'
STAT #18446744071472298536 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472298536 id=3 cnt=0 pid=2 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472298536 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472298536 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
Table avec une PK :
DROP TABLE PERE PURGE ; CREATE TABLE PERE (ID NUMBER, STRNG VARCHAR2 (30)) ;
ALTER TABLE PERE ADD CONSTRAINT PK_PERE PRIMARY KEY (ID);
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'PERE' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_PERE NORMAL UNIQUE DISABLED
ALTER SESSION FORCE PARALLEL DML;
INSERT /*+ PARALLEL */ INTO PERE
SELECT 1 + (Level -1) * 1 AS ID, TO_CHAR(1 + (Level -1) * 1)||'_MYTEST' CHAINE
FROM DUAL CONNECT BY LEVEL <= 100 ;
COMMIT ;
La trace montre qu'on est toujours en DIRECT-PATH :
STAT #18446744071472294336 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=3 pr=0 pw=0 time=120679 us)'
STAT #18446744071472294336 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=442 us)'
STAT #18446744071472294336 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
Maintenant je vais ajouter une table enfant, et on va voir le comportement avec une FK.
TRUNCATE TABLE PERE ;
CREATE TABLE ENFANT (ID NUMBER, P_ID NUMBER NOT NULL, STRNG2 VARCHAR2(100), CONSTRAINT PK_ENFANT PRIMARY KEY (ID, P_ID), CONSTRAINT FK_PERE_ENFANT FOREIGN KEY (P_ID) REFERENCES PERE (ID));
On exécute une autre fois l'insert :
ALTER SESSION FORCE PARALLEL DML;
INSERT /*+ PARALLEL */ INTO PERE
SELECT 1 + (Level -1) * 1 AS ID, TO_CHAR(1 + (Level -1) * 1)||'_MYTEST' CHAINE
FROM DUAL CONNECT BY LEVEL <= 100000 ;
COMMIT ;
STAT #18446744071472294336 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=3 pr=0 pw=0 time=203754 us)'
STAT #18446744071472294336 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=543 us)'
STAT #18446744071472294336 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=2 us cost=2 size=0 card=1)'
Avec un index NONUNIQUE sur la FK :
CREATE INDEX IDX_FK_PERE_ENFANT ON ENFANT( P_ID) ;
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL NONUNIQUE DISABLED
La trace affiche :
STAT #18446744071464440456 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=5 pr=0 pw=0 time=31720 us)'
STAT #18446744071464440456 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464440456 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464440456 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=548 us)'
STAT #18446744071464440456 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
Avec un index UNIQUE sur la FK :
DROP INDEX IDX_FK_PERE_ENFANT ;
Index dropped.
CREATE UNIQUE INDEX IDX_FK_PERE_ENFANT ON ENFANT( P_ID) ;
Index created.
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL UNIQUE DISABLED
On ne voit pas de différence :
STAT #18446744071472294336 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=5 pr=0 pw=0 time=30194 us)'
STAT #18446744071472294336 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=542 us)'
STAT #18446744071472294336 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=2 us cost=2 size=0 card=1)'
CREATE INDEX IDX_FK_PERE_ENFANT ON ENFANT( P_ID) ;
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL NONUNIQUE DISABLED
La trace affiche :
STAT #18446744071464440456 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=5 pr=0 pw=0 time=31720 us)'
STAT #18446744071464440456 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464440456 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464440456 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464440456 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=548 us)'
STAT #18446744071464440456 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
Avec un index UNIQUE sur la FK :
Index dropped.
CREATE UNIQUE INDEX IDX_FK_PERE_ENFANT ON ENFANT( P_ID) ;
Index created.
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL UNIQUE DISABLED
STAT #18446744071472294336 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=5 pr=0 pw=0 time=30194 us)'
STAT #18446744071472294336 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071472294336 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071472294336 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=542 us)'
STAT #18446744071472294336 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=2 us cost=2 size=0 card=1)'
Donc, apparemment le même comportement avec une FK, maintenant on va changer le comportement de la FK, on va le mettre en "mode" DEFERRED :
Avec une table enfant et une FK DEFERRED sans Index:
ALTER TABLE ENFANT DROP CONSTRAINT FK_PERE_ENFANT;
TRUNCATE TABLE PERE ;
ALTER TABLE ENFANT ADD CONSTRAINT FK_PERE_ENFANT FOREIGN KEY (P_ID) REFERENCES PERE (ID) DEFERRABLE INITIALLY DEFERRED;
On essaie une autre fois et on peut remarquer une modification dans le comportement, la charge de données ne se fait plus en DIRECT-PATH:
EXEC #18446744071472294336:c=24131,e=57071,p=8,cr=54,cu=40,mis=1,r=100,dep=0,og=1,plh=230221486,tim=3774639034135
STAT #18446744071472294336 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=4 pr=8 pw=0 time=38597 us)'
STAT #18446744071472294336 id=2 cnt=100 pid=1 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=542 us)'
STAT #18446744071472294336 id=3 cnt=1 pid=2 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=4 us cost=2 size=0 card=1)'
WAIT #18446744071472294336: nam='SQL*Net message to client' ela= 3 driver id=1650815232 #bytes=1 p3=0 obj#=5011953 tim=3774639034562
En plus c'est facile à voir avec :
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID b8c86pfbqpf7d, child number 0
-------------------------------------
INSERT /*+ PARALLEL */ INTO PERE SELECT :"SYS_B_0" + (Level
-:"SYS_B_1") * :"SYS_B_2" AS ID, TO_CHAR(:"SYS_B_3" + (Level
-:"SYS_B_4") * :"SYS_B_5")||:"SYS_B_6" CHAINE FROM DUAL CONNECT BY
LEVEL <= :"SYS_B_7"
Plan hash value: 230221486
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | | 2 (100)| |
| 1 | LOAD TABLE CONVENTIONAL | | | | |
| 2 | CONNECT BY WITHOUT FILTERING| | | | |
| 3 | FAST DUAL | | 1 | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------
Note
-----
- automatic DOP: Computed Degree of Parallelism is 1
Avec un index NONUNIQUE sur la FK DEFERRED :
CREATE INDEX IDX_FK_PERE_ENFANT ON ENFANT(P_ID);
Index created.
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL NONUNIQUE DISABLED
ALTER SESSION FORCE PARALLEL DML;
INSERT /*+ PARALLEL */ INTO PERE
SELECT 1 + (Level -1) * 1 AS ID, TO_CHAR(1 + (Level -1) * 1)||'_MYTEST' CHAINE
FROM DUAL CONNECT BY LEVEL <= 100 ;
COMMIT ;
La trace nous montre :
EXEC #18446744071464139560:c=5598,e=5596,p=0,cr=2,cu=8,mis=1,r=100,dep=0,og=1,plh=230221486,tim=3776115943347
STAT #18446744071464139560 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=2 pr=0 pw=0 time=1020 us)'
STAT #18446744071464139560 id=2 cnt=100 pid=1 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=558 us)'
STAT #18446744071464139560 id=3 cnt=1 pid=2 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
WAIT #18446744071464139560: nam='SQL*Net message to client' ela= 3 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=3776115943794
Avec un index UNIQUE sur la FK DEFERRED :
CREATE UNIQUE INDEX IDX_FK_PERE_ENFANT ON ENFANT( P_ID) ;
Index created.
SELECT INDEX_NAME, INDEX_TYPE, UNIQUENESS, COMPRESSION FROM DBA_INDEXES WHERE TABLE_NAME = 'ENFANT' ;
INDEX_NAME INDEX_TYPE UNIQUENES COMPRESS
------------------------------ --------------------------- --------- --------
PK_ENFANT NORMAL UNIQUE DISABLED
IDX_FK_PERE_ENFANT NORMAL UNIQUE DISABLED
La trace affiche :
EXEC #18446744071472294336:c=17427,e=34194,p=9,cr=28,cu=43,mis=1,r=100,dep=0,og=1,plh=230221486,tim=3777888567765
STAT #18446744071472294336 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=4 pr=9 pw=0 time=22736 us)'
STAT #18446744071472294336 id=2 cnt=100 pid=1 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=545 us)'
STAT #18446744071472294336 id=3 cnt=1 pid=2 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
Même avec une FK "DEFERRABLE INITIALLY IMMEDIATE" :
EXEC #18446744071472294336:c=6130,e=6129,p=0,cr=1,cu=6,mis=1,r=100,dep=0,og=1,plh=230221486,tim=3778185598851
STAT #18446744071472294336 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=1 pr=0 pw=0 time=1077 us)'
STAT #18446744071472294336 id=2 cnt=100 pid=1 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=448 us)'
STAT #18446744071472294336 id=3 cnt=1 pid=2 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=5 us cost=2 size=0 card=1)'
WAIT #18446744071472294336: nam='SQL*Net message to client' ela= 2 driver id=1650815232 #bytes=1 p3=0 obj#=-1 tim=3778185599222
Contournement :
Si on veut se trouver un moyen de faire la charge en mode DIRECT-PATH on pourrait simplement désactiver la FK si jamais elle est du type DEFERRED.
DELETE FROM PERE ;
COMMIT ;
ALTER TABLE ENFANT DISABLE CONSTRAINT FK_PERE_ENFANT;
ALTER SESSION FORCE PARALLEL DML;
INSERT /*+ PARALLEL */ INTO PERE
SELECT 1 + (Level -1) * 1 AS ID, TO_CHAR(1 + (Level -1) * 1)||'_MYTEST' CHAINE
FROM DUAL CONNECT BY LEVEL <= 100000 ;
COMMIT ;
ALTER TABLE ENFANT ENABLE CONSTRAINT FK_PERE_ENFANT;
Maintenant le comportement semble être le même qu'au début :
STAT #18446744071464313416 id=1 cnt=1 pid=0 pos=1 obj=0 op='PX COORDINATOR (cr=3 pr=0 pw=0 time=218111 us)'
STAT #18446744071464313416 id=2 cnt=0 pid=1 pos=1 obj=0 op='PX SEND QC (RANDOM) :TQ10002 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464313416 id=3 cnt=0 pid=2 pos=1 obj=0 op='INDEX MAINTENANCE PERE (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464313416 id=4 cnt=0 pid=3 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464313416 id=5 cnt=0 pid=4 pos=1 obj=0 op='PX SEND RANGE :TQ10001 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464313416 id=6 cnt=0 pid=5 pos=1 obj=0 op='LOAD AS SELECT (cr=0 pr=0 pw=0 time=0 us)'
STAT #18446744071464313416 id=7 cnt=0 pid=6 pos=1 obj=0 op='PX RECEIVE (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464313416 id=8 cnt=0 pid=7 pos=1 obj=0 op='PX SEND ROUND-ROBIN :TQ10000 (cr=0 pr=0 pw=0 time=0 us cost=2 size=0 card=1)'
STAT #18446744071464313416 id=9 cnt=100 pid=8 pos=1 obj=0 op='CONNECT BY WITHOUT FILTERING (cr=0 pr=0 pw=0 time=547 us)'
STAT #18446744071464313416 id=10 cnt=1 pid=9 pos=1 obj=0 op='FAST DUAL (cr=0 pr=0 pw=0 time=3 us cost=2 size=0 card=1)'
En bref, il existe plusieurs d'autres limitations lorsqu'on considère de faire un INSERT et on veut tirer profit du DIRECT-PATH.
Une liste détaillée se trouve ici :
https://docs.oracle.com/database/121/SQLRF/statements_9015.htm#SQLRF01604
Aucun commentaire:
Enregistrer un commentaire