IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Optimiser un delete sur un outer join (oracle 9)


Sujet :

Langage SQL

  1. #1
    Candidat au Club
    Inscrit en
    Décembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 5
    Points : 2
    Points
    2
    Par défaut Optimiser un delete sur un outer join (oracle 9)
    Bonjour,
    je cherche à optimiser une requête qui supprime de nombreux enregistrements selectionnés par un left outer join (oracle 9); la requête est la suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DELETE FROM TABLE1
    WHERE CHAMP IN (
    	SELECT T1.CHAMP
    	FROM TABLE2 T2, TABLE1 T1
    	WHERE 
    	  T1.CHAMP <> 0
    	  AND T2.CHAMP (+) = T1.CHAMP		
    		AND	T2.CHAMP IS NULL			
    		AND NOT EXISTS 
                             (SELECT CHAMP FROM TABLE3 T3 WHERE T1.CHAMP=T3.CHAMP));
    volumétrie:
    TABLE1: 1079939
    TABLE2: 1294241
    TABLE3: 79
    nombre d'enregistrements à supprimer: 40000

    J'ai déjà essayé de remplacé le "in" par un "exists":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DELETE FROM TABLE1 T1
      WHERE EXISTS(
      SELECT T1.CHAMP
    	FROM TABLE2 T2
    	WHERE
    	  T2.CHAMP (+) = T1.CHAMP
    	  AND T1.CHAMP <> 0
    	  AND    T2.CHAMP IS NULL    
    	  AND NOT EXISTS (SELECT CHAMP FROM TABLE3 T3 WHERE T1.CHAMP=T3.CHAMP)
    C'est encore plus long et aucun enregistrement n'est supprimé; je suppose que exists ne fait pas bon ménage avec la jointure.


    J'ai essayé de remplacer la jointure externe par un "not exists" mais ça reste un peu plus long que la 1ère requête. Ex:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DELETE from TABLE1 T1
    WHERE 
    	T1.TCHAMP <> 0
    	AND NOT EXISTS ( SELECT CHAMP FROM TABLE2 T2 WHERE T2.CHAMP = T.CHAMP)
    	AND NOT EXISTS ( SELECT CHAMP FROM TABLE3 T3 WHERE T.CHAMP=T3.CHAMP));
    Je pense que c'est le fait de supprimer les éléments avec un IN qui ralentit l'exécution mais je n'arrive pas à concilier la jointure externe directement avec le delete...
    Par exemple cette requête ne passe pas sur oracle 9:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DELETE FROM TABLE1 T1
    LEFT OUTER JOIN
    		TABLE2 T2 ON 
    				T2.CHAMP = T1.CHAMP
    WHERE 
    		T1.CHAMP <> 0
    		AND	T2.CHAMP IS NULL			
    		AND NOT EXISTS 
                (SELECT CHAMP FROM TABLE3 T3 WHERE T1.CHAMP=T3.CHAMP)

    Une idée?
    Merci

  2. #2
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 109
    Points : 28 436
    Points
    28 436
    Par défaut
    Je suppose que tes trois tables sont indexées sur CHAMP. Sinon, cela pourrait expliquer la lenteur de la requête.
    Autrement, c'est encore le NOT EXISTS qui devrait être le plus performant (avec des index !)

  3. #3
    Candidat au Club
    Inscrit en
    Décembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 5
    Points : 2
    Points
    2
    Par défaut re
    les tables sont indexées bien sur.
    en fait sur un select, l'utilisation d'un outer join est un peu plus rapide qu'un not exists :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT COUNT(*)
         FROM TABLE1 T1
         WHERE        
             T1.CHAMP <> 0
             AND NOT EXISTS ( SELECT CHAMP FROM TABLE2 T2 WHERE T1.CHAMP=T2.CHAMP)
             AND NOT EXISTS (SELECT CHAMP FROM TABLE3 T3 WHERE T1.CHAMP=T3.CHAMP)
    est plus long que :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT  COUNT(*)
    FROM  TABLE1 T1
    LEFT OUTER JOIN
    	TABLE2 T2 ON 
    			T2.CHAMP = T1.CHAMP
    	WHERE 
    	T2.CHAMP IS NULL	
    	AND T1.CHAMP <> 0				
    	AND NOT EXISTS (SELECT CHAMP FROM TABLE T3 WHERE T1.CHAMP=T3.CHAMP)

    La solution la plus rapide pour le delete serait donc de concilier le delete avec un outer join je suppose mais ça ne semble pas possible... aucune autre proposition?

  4. #4
    Candidat au Club
    Inscrit en
    Décembre 2005
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 5
    Points : 2
    Points
    2
    Par défaut re
    il faudrait écrire l'équivalent de cette requête qui ne marche pas sous oracle 9 (à cause du using):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    DELETE FROM TABLE1 T1
    USING
         LEFT OUTER JOIN
         TABLE2 T2 ON 
         T2.CHAMP = T1.CHAMP
    WHERE 
         T2.CHAMP IS NULL	
         AND	T1.CHAMP <> 0
         AND NOT EXISTS (SELECT CHAMP FROM TABLE3 T3 WHERE T1.CHAMP=T3.CHAMP)

Discussions similaires

  1. Problème sur requete outer join
    Par lindounette dans le forum Développement
    Réponses: 3
    Dernier message: 22/08/2011, 15h49
  2. Réponses: 6
    Dernier message: 08/11/2010, 10h52
  3. Réponses: 3
    Dernier message: 19/02/2008, 10h26
  4. Utilisation d'un filtre directement sur 'LEFT OUTER JOIN'
    Par lodan dans le forum Langage SQL
    Réponses: 2
    Dernier message: 04/03/2007, 17h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo