Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
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 18/02/2011, 14h37   #1
Membre éprouvé
 
Inscription : septembre 2004
Messages : 465
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 465
Points : 412
Points : 412
Par défaut Requête avec jointure en comparaison

(re)Bonjour.

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

Code :
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
Type de fichier : gif explan.gif (43,8 Ko, 11 affichages)
GoLDoZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 15h11   #2
Membre régulier
 
Inscription : septembre 2008
Messages : 84
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 84
Points : 88
Points : 88
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.
spdev666 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 15h18   #3
Membre expérimenté
 
François
Inscription : février 2010
Messages : 305
Détails du profil
Informations personnelles :
Nom : François

Informations forums :
Inscription : février 2010
Messages : 305
Points : 535
Points : 535
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.
Rams7s est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 15h21   #4
Membre éprouvé
 
Inscription : septembre 2004
Messages : 465
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 465
Points : 412
Points : 412
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...
GoLDoZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 15h23   #5
Membre éprouvé
 
Inscription : septembre 2004
Messages : 465
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 465
Points : 412
Points : 412
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.
GoLDoZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 16h36   #6
Membre éprouvé
 
Inscription : septembre 2004
Messages : 465
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 465
Points : 412
Points : 412
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...
GoLDoZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 17h04   #7
Membre éprouvé
 
Inscription : septembre 2004
Messages : 465
Détails du profil
Informations forums :
Inscription : septembre 2004
Messages : 465
Points : 412
Points : 412
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 :
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 :
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!
GoLDoZ est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 17h09   #8
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
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 ?
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 17h13   #9
Membre régulier
 
Inscription : septembre 2008
Messages : 84
Détails du profil
Informations forums :
Inscription : septembre 2008
Messages : 84
Points : 88
Points : 88
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
spdev666 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/02/2011, 17h15   #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 808
Points : 5 808
Ajoutez plutôt un petit jeu d’essai avec les "create table" et index etc. plus la requête et n’oubliez pas de préciser la version d’Oracle.
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/02/2011, 18h52   #11
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 808
Points : 5 808
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 ?
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 09h11.


 
 
 
 
Partenaires

Hébergement Web