Précédent   Forum des professionnels en informatique > Bases de données > Oracle > PL/SQL
PL/SQL Forum d'entraide sur le PL/SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/08/2011, 17h13   #1
Invité de passage
 
Inscription : février 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 13
Points : 3
Points : 3
Par défaut Oracle n'utilise pas mes index

Bonsoir à tous,

Je suis confronté à un problème d'optimisation de requête SQL, celle-ci prenant beaucoup trop de temps à l’exécution. Voici la requête :

Code :
1
2
3
4
5
SELECT DCO_NUMCSS, DCO_CODPRV, DCO_NUMFAC, DCO_ENVOI, DCO_DATENV, DCO_PRILIV, DCO_CODECE, DCO_IMMAT, DCO_DATPRL, DCO_DATIMT, DCO_NUMSER 
FROM DCONTA 
WHERE DCO_NUMCSS||DCO_NUMSER||DCO_NUMFAC 
NOT IN ( SELECT CSO_NUMCSS||CSO_NUMSER||CSO_NUMFAC 
FROM CSSOR );
Les deux tables incriminées, CSSOR et DCONTA sont indexées sur les trois colonnes que je requête dans la clause WHERE (un index de créé sur chacune des deux tables).

Lorsque je demande à ORacle de me fournir le plan d'execution de la requete (Explain Plan), celui-ci ne retourne deux TABLE ACCESS FULL. Je souhaiterais qu'il utilise mes index car je pense que le traitements de la requête irait largement plus vite...? Je ne suis pas doué en tuning / optimisation de requête, donc merci d'avance pour votre indulgence. J'ai pourtant lu par mal de cours mais j'ai surement dû passer à coté de quelques chose, et je ne comprends pas pourquoi.

Est-ce à cause de la concaténation ? Pourtant lorsque je ne prend qu'un seul champ, lui aussi indexé (j'ai testé la création d'index simples et supprimé ceux sur trois colonnes pour le tests) et le résultat est le même, Oracle n'utilise pas l'index. A savoir que j'ai également lancé la commande

"analyze table CSSOR compute statistics;"

Afin qu'Oracle puisse revoir le plan d’exécution.
Merci d'avance pour vos réponses.
Cordialement,

Paul
piloupolo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/08/2011, 17h56   #2
Modérateur
 
Avatar de al1_24
 
Homme Alain
Ingénieur d'études décisionnel
Inscription : mai 2002
Messages : 4 445
Détails du profil
Informations personnelles :
Nom : Homme Alain
Âge : 51
Localisation : France, Val de Marne (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études décisionnel
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 4 445
Points : 7 532
Points : 7 532
Et as-tu essayé avec EXISTS ?
Code :
1
2
3
4
5
6
7
8
9
10
SELECT  DCO_NUMCSS, DCO_CODPRV, DCO_NUMFAC, DCO_ENVOI, DCO_DATENV, DCO_PRILIV, DCO_CODECE, DCO_IMMAT, DCO_DATPRL, DCO_DATIMT, DCO_NUMSER 
FROM    DCONTA  DCO
WHERE   NOT EXISTS
        (   SELECT  1
            FROM    CSSOR   CSO 
            WHERE   DCO.DCO_NUMCSS  = CSO.CSO_NUMCSS
                AND DCO.DCO_NUMSER  = CSO.CSO_NUMSER
                AND DCO.DCO_NUMFAC  = CSO.CSO_NUMFAC 
        )
;
[EDIT] C'est bien sur NOT EXISTS !
__________________
Modérateur Langage SQL
Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
N'oubliez pas le bouton et pensez aux balises [code]
Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
al1_24 est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 16/08/2011, 19h27   #3
Membre Expert
 
Avatar de pachot
 
Homme Franck Pachot
DBA Oracle
Inscription : novembre 2007
Messages : 703
Détails du profil
Informations personnelles :
Nom : Homme Franck Pachot
Âge : 41
Localisation : Suisse

Informations professionnelles :
Activité : DBA Oracle
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : novembre 2007
Messages : 703
Points : 1 630
Points : 1 630
Bonjour,

1. La concaténation n'est pas une bonne idée. En plus elle peut renvoyer un résultat faux. Pourquoi nhe pas écrire:

Code :
1
2
3
4
5
SELECT DCO_NUMCSS, DCO_CODPRV, DCO_NUMFAC, DCO_ENVOI, DCO_DATENV, DCO_PRILIV, DCO_CODECE, DCO_IMMAT, DCO_DATPRL, DCO_DATIMT, DCO_NUMSER 
FROM DCONTA 
WHERE (DCO_NUMCSS,DCO_NUMSER,DCO_NUMFAC) 
NOT IN ( SELECT CSO_NUMCSS,CSO_NUMSER,CSO_NUMFAC 
FROM CSSOR );
2. L'utilisation de l'index (et le résultat aussi) peut dépendre du fait que (DCO_NUMCSS,DCO_NUMSER,DCO_NUMFAC) sont nullable ou non.

3. un accés par index n'est pas toujours le plus optimal

Cordialement,
Franck.

Cordialement,
Franck.
__________________
A lire sur mon blog Oracle - Articles d'Experts des articles traduits en français de Jonathan Lewis, Tom Kyte, Doug Burns, Cary Millsap, Greg Rahn ...
pachot est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 10h10   #4
Invité de passage
 
Inscription : février 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 13
Points : 3
Points : 3
Par défaut Merci

Merci Alain,

Effectivement, avec EXISTS, la requête utilise l'index. Le temps de traitement passe donc de plus de 20 minutes à peine 4 minutes.

Je pense que la clause NOT IN devait empêcher l'utilisation de l'index ?
Merci
Cordialement,

Paul
piloupolo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 11h05   #5
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Citation:
Envoyé par piloupolo Voir le message
Merci Alain,

Effectivement, avec EXISTS, la requête utilise l'index. Le temps de traitement passe donc de plus de 20 minutes à peine 4 minutes.

Je pense que la clause NOT IN devait empêcher l'utilisation de l'index ?
Merci
Cordialement,

Paul
Lorsque confronté à ce genre de problèmes de non utilisation d’index, il faut revenir à la base. Ici, dans le cas présent, la question qu’il faut se poser est ''comment le CBO interprète t-il l’operateur NOT IN?'' Et bien tout simplement le CBO transforme le NOT IN en <> (différent de).
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
mhouri.world> SELECT owner, object_name
  2  FROM t
  3  WHERE STATUS NOT IN ('VALID','INVALID');
 
no rows selected
 
mhouri.world> SELECT * FROM TABLE(dbms_xplan.display_cursor);
 
PLAN_TABLE_OUTPUT                                                               
--------------------------------------------------------------------------------
SQL_ID  f2gguvfc6nnwy, child number 0                                           
-------------------------------------                                           
SELECT owner, object_name FROM t WHERE STATUS NOT IN ('VALID','INVALID')        
 
Plan hash value: 2153619298                                                     
 
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |       |       |   136 (100)|          |      
|*  1 |  TABLE ACCESS FULL| T    |     6 |   234 |   136   (2)| 00:00:01 |      
--------------------------------------------------------------------------      
 
Predicate Information (IDENTIFIED BY operation id):                             
---------------------------------------------------                             
 
   1 - filter(("STATUS"<>'VALID' AND "STATUS"<>'INVALID'))                      
 
Note                                                                            
-----                                                                           
   - dynamic sampling used FOR this statement
Sachant que le NOT IN est transformé en <>, et sachant que l’opérateur différent (<>) ne peux pas être couvert par un simple index B-tree, vous avez donc votre réponse concernant la non utilisation de votre index.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
mhouri.world > CREATE TABLE t AS SELECT * FROM all_objects;
TABLE created.
 
 
mhouri.world > SELECT /*+ gather_plan_statistics */
  2         t.*
  3    FROM t
  4   WHERE STATUS != 'VALID'
  5  ;
 
 
mhouri.world > SELECT * FROM TABLE(dbms_xplan.display_cursor(NULL,NULL,'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT                                                                                                                                     
--------------------------------------------------------------------------------------
SQL_ID  5xtutwubr5xqv, child number 0                                                                                                                 
-------------------------------------                                                                                                                 
SELECT /*+ gather_plan_statistics */        t.* FROM t WHERE STATUS !=                                                                                
'VALID'                                                                                                                                                                                        
Plan hash value: 2153619298
------------------------------------------------------------------------------------                                                                  
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |                                                                  
------------------------------------------------------------------------------------                                                                  
|*  1 |  TABLE ACCESS FULL| T    |      1 |      6 |     30 |00:00:00.01 |     551 |                                                                  
------------------------------------------------------------------------------------                                                                  
 
Predicate Information (IDENTIFIED BY operation id):                                                                                                   
---------------------------------------------------                                                                                                   
   1 - filter("STATUS"<>'VALID')                                                                                                                      
 
Note                                                                                                                                                  
-----                                            
   - dynamic sampling used FOR this statement                                                                                                                                                      
22 rows selected.
Sachant qu’un B-tree index ne m’est d’aucune utilité dans ce cas, je vais plutôt créer un Function Based index sur la colonne STATUS, et répéter le même select
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 
mhouri.world > CREATE INDEX ind_fbi_status ON t (case when STATUS = 'VALID' then NULL else 'X' end );
INDEX created.
mhouri.world > SELECT /*+ gather_plan_statistics */
				2     t.*
				3  FROM t
				4  WHERE STATUS != 'VALID';
 
30 rows selected.
 
mhouri.world > SELECT * FROM TABLE(dbms_xplan.display_cursor(NULL,NULL,'ALLSTATS LAST'));
 
PLAN_TABLE_OUTPUT                                                                                                                                     
------------------------------------------------------------------------------------------
SQL_ID  5xtutwubr5xqv, child number 0                                                                                                                 
-------------------------------------                                                                                                                 
SELECT /*+ gather_plan_statistics */        t.* FROM t WHERE STATUS !=                                                                                
'VALID'                                                                                                                                               
 
Plan hash value: 2153619298                                                                                                                           
 
-----------------------------------------------------------------------------                                                                
| Id  | Operation         | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |                                                                  
------------------------------------------------------------------------------------                                                                  
|*  1 |  TABLE ACCESS FULL| T    |      1 |      6 |     30 |00:00:00.01 |     551 |                                                                  
------------------------------------------------------------------------------------                                                                  
 
Predicate Information (IDENTIFIED BY operation id):                                                                                                   
---------------------------------------------------                                                                                                   
 
   1 - filter("STATUS"<>'VALID')                                                                                                                      
 
Note                                                                                                                                                  
-----                                                                                                                                                 
   - dynamic sampling used FOR this statement                                                                                                         
 
22 rows selected.
Oups!!! Malgré la création de ce nouvel index, ce dernier n’a pas été utilisé par le CBO. Le CBO préfère encore faire un FULL TABLE SCAN. Savez vous pourquoi? Tout simplement pour que le CBO puisse utiliser le function based (FBI) index, il faut que la clause where de ma requête et la définition de mon FBI coïncident parfaitement. C’est pourquoi je vais réécrire ma requête comme suit :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
mhouri.world > SELECT /*+ gather_plan_statistics */
  2         t.*
  3    FROM t
  4    WHERE CASE
  5            WHEN STATUS = 'VALID'
  6               THEN NULL
  7            ELSE 'X'
  8         END = 'X';
 
 
30 rows selected.
 
 mhouri.world >SELECT * FROM TABLE(dbms_xplan.display_cursor(NULL,NULL,'ALLSTATS LAST'));
 
PLAN_TABLE_OUTPUT                                                                                                                                     
--------------------------------------------------------------------------------------------------------
SQL_ID  32fcmm91ywcqf, child number 0                                                                                                                 
-------------------------------------                                                                                                                 
SELECT /*+ gather_plan_statistics */        t.*   FROM t  WHERE CASE           WHEN STATUS =                                                          
'VALID'              THEN NULL           ELSE 'X'        END = 'X'                                                                                    
 
Plan hash value: 3817300654                                                                                                                           
 
--------------------------------------------------------------------------------------------------------                                              
| Id  | Operation                   | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |                                              
--------------------------------------------------------------------------------------------------------                                              
|   1 |  TABLE ACCESS BY INDEX ROWID| T              |      1 |      6 |     30 |00:00:00.01 |      14 |                                              
|*  2 |   INDEX RANGE SCAN          | IND_FBI_STATUS |      1 |    130 |     30 |00:00:00.01 |       3 |                                              
--------------------------------------------------------------------------------------------------------                                              
 
Predicate Information (IDENTIFIED BY operation id):                                                                                                   
---------------------------------------------------                                                                                                   
 
   2 - access("T"."SYS_NC00014$"='X')                                                                                                                 
 
Note                                                                                                                                                  
-----                                                                                                                                                 
   - dynamic sampling used FOR this statement                                                                                                                                                                                                                                                             
 
23 rows selected.

Et voilà enfin, le CBO a fini par utiliser mon index.

Conclusion
Dans votre cas il y a plusieurs points à considérer
(a) Concaténation de colonnes indexées. Comment réagit le CBO dans ce cas ? je ne l’ai pas essayé encore
(b) Dans le cas où vous n’avez utilisé qu’une seule colonne, c’est bien le NOT IN qui empêche l’utilisation de l’index sur cette colonne. Il faudra penser plutôt à la création d’un function based index dans cette situation
(c) La liste de votre NOT IN est constituée d’un select sur une autre table. A votre place j’utiliserai plutôt un not exists comme suit:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 
SELECT 
  DCO_NUMCSS,
  DCO_CODPRV,
  DCO_NUMFAC,
  DCO_ENVOI,
  DCO_DATENV,
  DCO_PRILIV,
  DCO_CODECE,
  DCO_IMMAT,
  DCO_DATPRL,
  DCO_DATIMT,
  dco_numser
FROM dconta a
WHERE 
   NOT EXISTS (SELECT NULL
               FROM cssor b
               WHERE b.dco_numcss = a.dco_numcss
              );
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 17/08/2011, 11h45   #6
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 311
Points : 5 810
Points : 5 810
Faites attention :
  • aux Not In et les Nulls sinon le résultat n’est pas correct.
  • aux divers cases d’utilisation d’un index
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    SQL> EXPLAIN plan FOR
      2  SELECT empno
      FROM emp
     WHERE empno <> 7369
      3    4    5  ;
     
    Explicité.
     
    SQL> SELECT * FROM TABLE(dbms_xplan.display);
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    Plan hash value: 2855544112
     
    ---------------------------------------------------------------------------
    | Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT |        |    13 |    52 |     1   (0)| 00:00:01 |
    |*  1 |  INDEX FULL SCAN | PK_EMP |    13 |    52 |     1   (0)| 00:00:01 |
    ---------------------------------------------------------------------------
     
    Predicate Information (IDENTIFIED BY operation id):
    ---------------------------------------------------
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
     
       1 - filter("EMPNO"<>7369)
     
    13 ligne(s) sélectionnée(s).
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 11h59   #7
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Citation:
Envoyé par mnitu Voir le message
Faites attention :[list][*]aux Not In et les Nulls sinon le résultat n’est pas correct.[*]aux divers cases d’utilisation d’un index
Tout à fait

Tiré de mon blog

Citation:

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
Warning: the above FBI INDEX will NOT work correctly IF the STATUS COLUMN IS allowed TO be NULL.
 
 mhouri.world> UPDATE t  
 2  SET STATUS = NULL 
 
3  WHERE STATUS != 'VALID' 
4  AND rownum <= 4;  
 
4 rows updated.  
 
mhouri.world> commit;  
 
Commit complete.  
 
mhouri.world> SELECT count(1)  
2    FROM t  
3   WHERE STATUS != 'VALID';  
 
 COUNT(1)  
----------  
   26  
 
mhouri.world>  SELECT count(1)  
2       FROM t  
3       WHERE CASE 
4               WHEN STATUS = 'VALID' 
5                  THEN NULL 
6               ELSE 'X' 
7            END = 'X';  
 
 COUNT(1)  
 ----------  
   30 
 
!!!
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 
 
mhouri.world> CREATE INDEX ind_fbi_status ON t(case when nvl(STATUS,'VALID') = 'VALID' then NULL else 'X' end);  
 
INDEX created.  
 
mhouri.world> SELECT count(1)  
2  FROM t  
3  WHERE case when nvl(STATUS,'VALID') = 'VALID' 
4                 then NULL 
5             else 'X' 
6             end = 'X';  
 
COUNT(1)  
----------  
26  
 
mhouri.world> SELECT * FROM TABLE(dbms_xplan.display_cursor);  
 
PLAN_TABLE_OUTPUT  
 
-------------------------------------------------------------------------------------  
 
SQL_ID  ffj2y4c2q8vup, child number 0  
 
 -------------------------------------  
 
 SELECT count(1) FROM t WHERE case when nvl(STATUS,'VALID') = 'VALID' 
 
 then NULL            else 'X'            end = 'X' 
 Plan hash value: 3388779105  
 
 ------------------------------------------------------------------------------------  
 
| Id  | Operation         | Name           | Rows  | Bytes | Cost (%CPU)| Time     |  
 
------------------------------------------------------------------------------------  
 
|   0 | SELECT STATEMENT  |                |       |       |     1 (100)|          |  
 
|   1 |  SORT AGGREGATE   |                |     1 |     5 |            |          |  
 
|*  2 |   INDEX RANGE SCAN| IND_FBI_STATUS |     6 |    30 |     1   (0)| 00:00:01 |  
 
------------------------------------------------------------------------------------   
 
Predicate Information (IDENTIFIED BY operation id):  
---------------------------------------------------  
2 - access("T"."SYS_NC00014$"='X')  
 
Note  
 
-----  
- dynamic sampling used FOR this statement
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 13h21   #8
Invité de passage
 
Inscription : février 2007
Messages : 13
Détails du profil
Informations forums :
Inscription : février 2007
Messages : 13
Points : 3
Points : 3
Par défaut Merci

Merci à tous, super les explications, j'ai parfaitement compris Tout cela ira mieux d'ici quelques semaines, lorsque j'aurai assisté à ma formation Oracle PL/SQL
Un grand merci à vous tous pour l'exactitude et la rapidité de vos réponses.
piloupolo est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 14h27   #9
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Marius,

Pour en revenir au cas que vous avez posté

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
SQL> EXPLAIN plan FOR
  2  SELECT empno
  FROM emp
 WHERE empno <> 7369
  ;
 
Explicité.
 
SQL> SELECT * FROM TABLE(dbms_xplan.display);
 
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------
Plan hash value: 2855544112 
---------------------------------------------------------------------------
| Id  | Operation        | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT |        |    13 |    52 |     1   (0)| 00:00:01 |
|*  1 |  INDEX FULL SCAN | PK_EMP |    13 |    52 |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------
 
Predicate Information (IDENTIFIED BY operation id):
---------------------------------------------------
 
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------
    1 - filter("EMPNO"<>7369)
Ceci ne veut pas dire que notre index PK_EMP a bien couvert notre where clause where empno <> 7369. Mais ceci veut dire que le CBO, voyant que la seule colonne à sélectionner existe au sein de l'index PK_EMP, il a estimé que l'accès à l'index dans ce cas est moins couteux qu'un accès à la table. Il accède alors à cet index (non pas pour trouver un rowid vers la table, mais bien pour trouver l'enregistrement recherché) en faisant par la suite un filtre (empno <> 7369) afin de jeter ce qui ne convient pas et garder le reste.

Si par exemple j'ajoute une seule colonne à la requête, l'index n'est plus, ni accédé, ni utilisé
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 
mhouri.world> EXPLAIN plan FOR
  2  SELECT empno, ename
  3  FROM emp
  4  WHERE empno <> 7369;
 
Explained.
 
mhouri.world> SELECT * FROM TABLE (dbms_xplan.display);
 
PLAN_TABLE_OUTPUT                                                               
--------------------------------------------------------------------------------
Plan hash value: 2872589290                                                     
 
--------------------------------------------------------------------------      
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |      
--------------------------------------------------------------------------      
|   0 | SELECT STATEMENT  |      |    14 |   140 |     5   (0)| 00:00:01 |      
|*  1 |  TABLE ACCESS FULL| EMP  |    14 |   140 |     5   (0)| 00:00:01 |      
--------------------------------------------------------------------------      
 
Predicate Information (IDENTIFIED BY operation id):                             
---------------------------------------------------                                                                                                            
   1 - filter("EMPNO"<>7369)                                                    
 
13 rows selected.
Par contre si j'enrichi mon index avec la colonne ename, l'index sera de nouveau désiré par le CBO

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
 
mhouri.world > CREATE INDEX emp_enm ON emp (empno, ename);
 
INDEX created.
 
mhouri.world > EXPLAIN plan FOR
  2  SELECT empno
  3       ,ename
  4  FROM emp
  5  WHERE empno <> 7369;
 
Explained.
 
mhouri.world > SELECT * FROM TABLE (dbms_xplan.display);
 
PLAN_TABLE_OUTPUT                                                               
--------------------------------------------------------------------------------
Plan hash value: 1499357153                                                     
 
----------------------------------------------------------------------------    
| Id  | Operation        | Name    | Rows  | Bytes | Cost (%CPU)| Time     |    
----------------------------------------------------------------------------    
|   0 | SELECT STATEMENT |         |    14 |   140 |     1   (0)| 00:00:01 |    
|*  1 |  INDEX FULL SCAN | EMP_ENM |    14 |   140 |     1   (0)| 00:00:01 |    
----------------------------------------------------------------------------    
 
Predicate Information (IDENTIFIED BY operation id):                             
---------------------------------------------------                                                                                                            
   1 - filter("EMPNO"<>7369)                                                    
 
13 rows selected.
C'est pourquoi il est parfois très judicieux de créér un index qui "match" les colonnes sélectionées afin d'eviter l'accès à la table
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 17h02   #10
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 311
Points : 5 810
Points : 5 810
Mohamed,
C’était juste pour nuancer vos propos
Citation:
« …et sachant que l’opérateur différent (<>) ne peux pas être couvert par un simple index B-tree »
«Sachant qu’un B-tree index ne m’est d’aucune utilité dans ce cas …»
qui ont sonnées pour moi comme des autres "fausses" vérités : Oracle n’index pas les nulls, utilisez toujours des variables de liaisons dans vos requêtes, etc.

D’autre part je trouve un peu forcé l’idée de créer un index fonctionnel dans ce cas.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 17h12   #11
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Citation:
Envoyé par mnitu Voir le message
Mohamed,
C’était juste pour nuancer vos propos

qui ont sonnées pour moi comme des autres "fausses" vérités : Oracle n’index pas les nulls, utilisez toujours des variables de liaisons dans vos requêtes, etc.

D’autre part je trouve un peu forcé l’idée de créer un index fonctionnel dans ce cas.
Ok marius, merci. Je préfère les réponses directes. Cela me permettra d'avancer plus vite
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/08/2011, 19h42   #12
Membre Expert
 
Avatar de pachot
 
Homme Franck Pachot
DBA Oracle
Inscription : novembre 2007
Messages : 703
Détails du profil
Informations personnelles :
Nom : Homme Franck Pachot
Âge : 41
Localisation : Suisse

Informations professionnelles :
Activité : DBA Oracle
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : novembre 2007
Messages : 703
Points : 1 630
Points : 1 630
Bonjour,

Citation:
Envoyé par piloupolo Voir le message
Je pense que la clause NOT IN devait empêcher l'utilisation de l'index ?
Les requêtes avec NOT IN ne ramènent pas le même résultat. Ils ne sont équivalentes que si la sous requête ne renvoie jamais de NULL. Et lorsque elle ne ramène jamais de null (parce que les colonnes sont not null ou qu'on rajoute des prédicats is not null) l'index est utilisé dans les 2 cas.

Le problème n'est pas d'écrire d'une façon ou d'une autre. L'optimiseur va de toute façon le réécrire à sa sauce. Mais d'être précis sur les données et le résultat qu'on veut.

Cordialement,
Franck.
__________________
A lire sur mon blog Oracle - Articles d'Experts des articles traduits en français de Jonathan Lewis, Tom Kyte, Doug Burns, Cary Millsap, Greg Rahn ...
pachot est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/08/2011, 12h31   #13
Membre expérimenté
 
Homme Mohamed Houri
Inscription : mars 2010
Messages : 286
Détails du profil
Informations personnelles :
Nom : Homme Mohamed Houri
Localisation : France

Informations forums :
Inscription : mars 2010
Messages : 286
Points : 563
Points : 563
Pour plus d'information à ce sujet

http://richardfoote.wordpress.com/20...-not-now-john/

http://jonathanlewis.wordpress.com/2007/02/25/not-in/
__________________
Bien Cordialement
www.hourim.wordpress.com
Mohamed.Houri est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/08/2011, 14h30   #14
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 311
Points : 5 810
Points : 5 810
Citation:
Envoyé par Mohamed.Houri Voir le message
Pour plus d'information à ce sujet

http://richardfoote.wordpress.com/20...-not-now-john/
...
Citation:
Therefore the CBO simply ignores indexes when costing a NOT EQUAL condition. Why bother going to all the overhead of calculating the cost of using an index to retrieve the vast majority of rows when a Full Table Scan is going to be the cheaper alternative in the vast majority of such cases. So the CBO doesn’t even bother trying and ignores all indexes that could potentially be used to retrieve the rows based on the NOT EQUAL condition.
Comme vous l'avez déjà constaté il se trompe royalement.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/08/2011, 14h33   #15
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 311
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 311
Points : 5 810
Points : 5 810
Citation:
Envoyé par Mohamed.Houri Voir le message
Pour plus d'information à ce sujet
http://jonathanlewis.wordpress.com/2007/02/25/not-in/
Utile mais, je ne vois rien de nouveau par rapport à notre discussion.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h29.


 
 
 
 
Partenaires

Hébergement Web