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

SQL Oracle Discussion :

Requête avec jointure en comparaison


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut Requête avec jointure en comparaison
    (re)Bonjour.

    J'ai un souci de performances sur cette requête assez simple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    WITH table1 AS (
    SELECT 1 AS col1, 150 AS col2 FROM dual union ALL
    SELECT 2 AS col1, 250 AS col2 FROM dual union ALL
    SELECT 3 AS col1, 350 AS col2 FROM dual union ALL
    SELECT 4 AS col1, 450 AS col2 FROM dual union ALL
    SELECT 5 AS col1, 550 AS col2 FROM dual union ALL
    SELECT 6 AS col1, 650 AS col2 FROM dual),
    table2 AS (
    SELECT 1 AS col1, 100 AS borneinf, 199 AS bornesup FROM dual union ALL
    SELECT 2 AS col1, 200 AS borneinf, 299 AS bornesup FROM dual union ALL
    SELECT 3 AS col1, 300 AS borneinf, 399 AS bornesup FROM dual union ALL
    SELECT 4 AS col1, 400 AS borneinf, 499 AS bornesup FROM dual)
    SELECT t1.*, t2.col4
      FROM table1 t1, table2 t2
    WHERE t1.col2 >= t2.borneinf
       AND  t1.col2 <= t2.bornesup;
    J'ai des index sur les éléments de comparaison (t1.col2, t2.borneinf et t2.bornesup) qui sont des NUMBER.

    t1 fait 64 000 lignes, et t2 fait 134 000 lignes. L'insertion de ce select dans une table vide prend 2h...... alors que t1 contiendra 900 000 lignes.

    L'explain plan est en pièce joint. C'est le MERGE qui coince...

    Une précision: dans la table t2, chaque intervalle [borneinf; bornesup] n'est qu'en un seul exemplaire, et les intervalles ne se chevauchent pas. Il faudrait que pour chaque ligne, la comparaison s'arrête dès qu'on en a trouvé un (il peut n'y avoir aucun intervalle).

    Merci pour votre aide!
    Images attachées Images attachées  

  2. #2
    Membre éprouvé
    Inscrit en
    Septembre 2008
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 101
    Par défaut
    Bonjour,

    Est ce que l'exécution du select seul (sans insert) prend autant de temps ? (je suppose que non)
    Si non, quel est la structure de la table à remplir ? comporte t elle des indexes, des clés étrangères ?
    Si oui, essayez de désactiver les index (et si besoin les clé étrangères) le temps de l'insertion, ca devrait limiter le travail de la base durant l'insert.

  3. #3
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2010
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 412
    Par défaut CREATE TABLE
    Si c'est pour mettre dans une table vide, c'est plus rapide de faire un create table qu'un gros insert.

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Citation Envoyé par Rams7s Voir le message
    Si c'est pour mettre dans une table vide, c'est plus rapide de faire un create table qu'un gros insert.
    Oui mais non!
    Cette table sera vidée et remplie tous les jours, et j'ai deux insert successifs à faire.

  5. #5
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Mon DBA sèche aussi. Personne n'a une idée?

    Il doit forcément y avoir un truc pour éviter qu'une simple comparaison ne provoque pas un produit cartésien...

  6. #6
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 953
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Comment est (sont) créé l'index sur table2 ?
    Un index composite sur (borneinf,bornesup) ou 2 index séparés ? Si l'index est composite, est il unique ? ça pourrait donner des infos à l'optimiseur.
    Les stats sont elles à jour et y a t il des histogrammes sur les colonnes borneinf et bornesup ?
    Analyser l'index est aussi une bonne chose.
    Quelle est la version d'oracle ?

  7. #7
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Le SELECT ne prend pas autant de temps (SqlDeveloper me ramène les 50 premières lignes en 11s) mais c'est déjà trop.
    La table cible n'a ni index, ni clé primaire (je l'ai virée avant l'insertion), juste quelques contraintes not null. Les stats sont calculées sur les 3 tables.

    Il y a un vrai problème sur le SELECT, car le MERGE me fait visiter 21 millions de lignes...

  8. #8
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    RESOLU!

    Le DBA (c'est mon pote!!!!) a trouvé la soluce en cherchant sur ORAFAQ: Tuning "BETWEEN" Queries.
    Au chapitre "Range Table Single-row Lookup" de la page.

    Le truc: on remplace
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT *
    FROM   orders o
    ,      delivery_method m
    WHERE  o.order_amt BETWEEN m.lower_bound and m.upper_bound
    par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT /*+ordered use_nl(m)*/ *
    FROM   orders o
    ,      delivery_method m
    WHERE  o.order_amt BETWEEN m.lower_bound and m.upper_bound
    AND    m.upper_bound =  (
           SELECT min(m1.upper_bound)
           FROM   delivery_method m1
           WHERE  m1.upper_bound >= o.order_amt
    )
    La clause ajoutée sur la bornesup restreint le champ d'action et le forçage (obligatoire!) de l'index fait le reste.

    Je suis passé de 2 heures à ...... 2 secondes!!!

    A garder précieusement pour l'utilisation des BETWEEN!

  9. #9
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Par défaut
    Citation Envoyé par GoLDoZ Voir le message
    RESOLU!

    Le DBA (c'est mon pote!!!!) a trouvé la soluce en cherchant sur ORAFAQ: Tuning "BETWEEN" Queries.
    ...
    Avez vous remarqué à la fin de l'article que le Sort-Merge Join se comporte mieux ?

  10. #10
    Membre éprouvé
    Inscrit en
    Septembre 2008
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 101
    Par défaut
    En fait, ce n est pas vraiment un produit cartesien : 64*134 ~ 8500 >> 21, mais c'est quand meme une combinatoire de possibilités

    Une solution de contournement serait de traiter les lignes de table1 par paquets de n lignes triées. Ca permettrait de limiter les combinaisons

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Requête avec jointure
    Par Maglight dans le forum Langage SQL
    Réponses: 4
    Dernier message: 17/11/2005, 09h57
  2. optimisation d'une requête avec jointure
    Par champijulie dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 07/07/2005, 09h45
  3. Requête avec jointures
    Par Corben dans le forum Langage SQL
    Réponses: 4
    Dernier message: 16/11/2004, 12h55
  4. Mise à jour de table impossible après requête avec jointure
    Par sto dans le forum Bases de données
    Réponses: 5
    Dernier message: 17/03/2004, 13h24
  5. problème de requête avec jointures
    Par tinhat dans le forum Requêtes
    Réponses: 7
    Dernier message: 11/08/2003, 10h33

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