Optimisation d'une requête de mise à jour

cs_josserand Messages postés 14 Date d'inscription vendredi 11 juin 2004 Statut Membre Dernière intervention 18 octobre 2006 - 18 oct. 2006 à 14:34
mementosql Messages postés 4 Date d'inscription samedi 23 août 2008 Statut Membre Dernière intervention 27 août 2008 - 23 août 2008 à 15:58
Bonjour,


J'ai besoin de créer des requêtes de mises à jour, appelant une sous-requête. Du genre :

<!-- BEGIN TEMPLATE: bbcode_code -->

Code :

UPDATE TABLE1 T1
SET T1.CHAMP1 =
(
SELECT T2.CHAMP1
FROM TABLE2 T2
WHERE T1.CHAMP2 = T2.CHAMP2
);

<!-- END TEMPLATE: bbcode_code -->

Seulement, cette requête met 4H pour mettre à jour 300 000 lignes.
Normal, puisque pour chaque ligne, elle effectue une requête qui, elle
seule, met 12 secondes.


Connaitriez-vous un moyen d'éviter d'exécuter la sous-requête pour
chaque ligne à mettre à jour, ou, plus généralement, un moyen
d'optimiser cette requête ?


Merci pour votre éventuelle aide

7 réponses

nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 36
18 oct. 2006 à 15:06
Salut,

Je pense que ta requete est longue car elle update toute la table

il n'y a pas de condition where sur le update.

UPDATE TABLE1 T1
SET T1.CHAMP1 =
(
SELECT T2.CHAMP1
FROM TABLE2 T2
WHERE T1.CHAMP2 = T2.CHAMP2
) WHERE ??????

Sinon pour faire plus simple

il y a la solution

declare @n as int
SELECT @n = T2.CHAMP1
FROM TABLE2 T2
WHERE T1.CHAMP2 = T2.CHAMP2

 
UPDATE TABLE1 T1
SET T1.CHAMP1 = @n

Désolé c'est du pseudo sqlserver, mais ca dpois repondre à ton problème.

Bon courage.
0
cs_josserand Messages postés 14 Date d'inscription vendredi 11 juin 2004 Statut Membre Dernière intervention 18 octobre 2006
18 oct. 2006 à 15:48
Je n'ai aucune condition à mettre après le update, puisque je dois le faire sur toute la table.

Pour ta 2ème solution, ça pourrait m'offrir un début de solution... Mais je n'ai pour le moment pas réussi à trouver le moyen de créer des variables sous Oracle, différent de SQL Server, en effet.

Cette solution amène une autre question : @n peut-il être un tableau ? Puisque le SELECT va ramener autant de valeur qu'il y a d'enregistrements.

En attendant, je vais essayer d'approfondir cette solution, je te remercie.
0
nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 36
18 oct. 2006 à 15:54
Salut

Il faut absolument que ton select revoie une seule valeur.

Car je ve vois pas commetn ton oracle peux affecter un tableau dans une valeur
numerique ou chaine ;-)

Pour la constrcution d'une proc stocke en oracle, il faut faire
DECLARE

    a NUMBER;

    b NUMBER;

BEGIN

    SELECT e,f INTO a,b FROM T1 WHERE e>1;

    INSERT INTO T1 VALUES(b,a);

END;
0
cs_josserand Messages postés 14 Date d'inscription vendredi 11 juin 2004 Statut Membre Dernière intervention 18 octobre 2006
18 oct. 2006 à 17:59
Oui, dans le cas où j'effectue mon SELECT tout seul, plusieurs valeurs sont renvoyées. Par contre, quand ce même SELECT est dans un UPDATE (cf. ma requête du 1er message), une seule valeur est renvoyé, en jointure avec la table à mettre à jour... donc, pas d'erreur.

Pour me renvoyer une seule valeur, mon SELECT seul devrait ressembler à
SELECT T2.CHAMP1
FROM TABLE2 T2
WHERE T2.CHAMP2 = 'maValeur';

et non à

SELECT T2.CHAMP1
FROM TABLE2 T2, TABLE1 T1
WHERE T1.CHAMP2 = T2.CHAMP2;


En gros, pour que je puisse me servir de ça, il faudrait que j'arrive à stocker toutes les valeurs dans un tableau, pour ensuite faire mon UPDATE par rapport à chaque valeur de ce tableau (du style avec une boucle pour avoir Tab[i])...

Bref, ne nous fatiguons plus sur ce problème... si ce n'est pour notre culture du SQL, car j'ai trouvé la solution avec un logiciel de gestion de données : Sunopsis... Il me fait ça en quelques secondes !

Merci à toi, et si tu as compris mes contraintes et que tu connais la réponse, je reste à l'écoute
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 36
18 oct. 2006 à 18:43
C'est un curseur qu'il te faut sinon


Voila
0
cs_Malkuth Messages postés 268 Date d'inscription samedi 22 février 2003 Statut Membre Dernière intervention 24 avril 2013 4
19 oct. 2006 à 13:52
Sous SQL Server tu peux faire :

UPDATE
   TABLE1 T1
SET
   CHAMP1 = T2.CHAMP1
FROM
   TABLE1 T1
      INNER JOIN
   TABLE2 T2
      ON T1.CHAMP2 = T2.CHAMP2;

En effet si une seule table peut être mise a jour,
on peut par contre utiliser les autres directement
Pour récupérer les valeurs, faire des jointure,
établir des conditions...

Je pense que le code est facilement transpossable à Oracle...




<!-- END TEMPLATE: bbcode_code -->
0
mementosql Messages postés 4 Date d'inscription samedi 23 août 2008 Statut Membre Dernière intervention 27 août 2008 1
23 août 2008 à 15:58
Sous Oracle, l update via jointure peut tout a fait etre effectué comme énoncé iniatialement,
Le probleme, tu l as dis c'est le fait que ta sous requete mette 12s.
Essaies, si tu peux, de mettre un index sur t2.champs2, et ensuite, puisque que seul un enregistrement doit etre présent, ajoute and rownum = 1, ca peut aider.
Enfin, ne pense pas que la sous requete est exécutée autant de fois qu'il y a de mise à jour, oracle optimise ca en interne.

en gros essaie d optimiser ton select (ta jointure), la mise à jour suivra.

MS
http://aide-oracle.blogspot.com
0
Rejoignez-nous