2010-03-03 6 views
2

J'ai une déclaration de mise à jour qui va ainsi:déclaration de mise à jour en utilisant clause IN numéro

update tableA 
    set val1='X', val2='Y' 

where id in (
    select id from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY') 

Maintenant, l'instruction SELECT interne fonctionne en 10 minutes de retour de 1000 dossiers (à la fois tableA et tableB ont environ 10 mil enregistre chaque)

L'ensemble de la déclaration de mise à jour dure 3 heures (ne sont pas encore pour l'achèvement attendu)

Toutes les idées?

+0

Il exécute probablement la requête interne pour chaque ligne de la tableA. Quelle base de données utilisez-vous? –

+0

base de données est DB2 – Peter

+0

y a-t-il des index sur la table A impliquant les colonnes modifiées? Le temps système peut ralentir le processus –

Répondre

2

Il n'y a probablement aucun index sur la colonne tableA.id ou le type de tableA.id ne correspond pas au type renvoyé par select.

[EDIT] Vous pouvez essayer cette syntaxe bizarre:

update (
    select val1, val2 from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY' 
) tmp 
set val1='X', val2='Y' 

Cela crée une table temporaire qui est toujours liée à la table d'origine, de sorte que vous pouvez mettre à jour les valeurs qui le retour de sélection et ils apparaître dans le tableau d'origine.

[EDIT2] J'ai manqué le fait que vous sélectionnez et mettez à jour la même table (c'est-à-dire id est la même colonne). Dans ce cas, le type n'a évidemment pas d'importance et vous ne devriez même pas avoir besoin d'un index (puisque le select renvoie déjà les lignes correctes).

Essayez EXPLAIN PLAN pour voir si quelque chose d'autre se passe. En outre, vous pourriez entrer en conflit avec un autre processus qui met également à jour la même table (c'est-à-dire que vous avez un verrou quelque part). AQT a un moniteur qui peut montrer ces choses. Si vous le pouvez, obtenez l'AQT et utilisez-le. Il a un excellent support pour DB2 et est meilleur que tout ce que j'ai vu jusqu'ici.

+1

C'est la même colonne sur la même table ... pas sûr comment il ne correspondrait pas aux types ... –

+1

+1 - bon appel. En outre, vous pouvez essayer un EXPLAIN sur votre requête. –

+1

Il y a un index sur tableA.id Je ne pense pas que le type de tableA.id soit valide ici. – Peter

0

J'ai eu du succès dans le passé en cassant la sous-requête, et en stockant sa sortie sur une table temporaire. par exemple.

CREATE TEMPORARY TABLE my_ids (id INT); 

INSERT INTO my_ids select id from tableA A 

    LEFT JOIN tableB B ON A.col1=B.col1 and A.col2=B.col2 

    where A.col3='xx' and B.col3= 'YY'; 

update tableA 
    set val1='X', val2='Y' 
WHERE id IN (SELECT id FROM my_ids); 

Si votre goût spécifique SQL a une sorte de MISE À JOUR REJOIGNEZ-esque syntaxe (par exemple de tableA MISE À JOUR À L'AIDE my_ids) qui peut également être intéressant d'essayer

+0

c'est effectivement une solution mais c'est un travail par lots quotidien et les DBA ne sont pas cool avec la création de ces tables temporaires. – Peter

+0

Vous pouvez utiliser des tables temporaires globales, qui n'existent que jusqu'à ce que l'application qui les a déclarées termine sa connexion à la base de données. –

0

Avez-vous des indices sur l'une des colonnes? Si vous n'avez pas d'index sur tableA.col1, tableB.col1, tableA.col2, tableB.col2, tableA.col3 et tableB.col3 cela pourrait expliquer les longs temps de recherche. Si vous n'avez pas d'index pour ces comparaisons, vous serez obligé de balayer toute la table, ce qui sera lent.

En outre, même si vous avez des index, vous devez vérifier si vos statistiques sont à jour; Si ce n'est pas le cas, cela peut causer des problèmes même si la structure physique des index est bonne. Vous ne mentionnez pas la base de données que vous utilisez, mais si vous avez les moyens de l'obtenir pour vous indiquer le plan d'exécution de votre requête, vous pouvez l'utiliser pour déterminer ce qu'il fait et prendre les mesures appropriées pour l'ajouter les index dont vous aurez besoin.

0

Vous devriez essayer une jointure de mise à jour car cela devrait améliorer le plan d'explication.

update tableA A, tableB B 
set A.val1='X', A.val2='Y' 
where A.col1 = B.col1 and A.col2 = B.col2 
    and A.col3 = 'xx' and B.col3 = 'YY' 

Les index aideront clairement avec cette jointure comme d'autres l'ont déjà indiqué. Veuillez copier les résultats EXPLAIN si vous voulez que nous vérifiions que les index sont utilisés.

+0

Cette syntaxe n'est pas prise en charge dans DB2. –

+0

DB2 n'a pas été spécifié lorsque j'ai écrit ceci. –

0

D'autres ont suggéré d'utiliser EXPLAIN pour aider à identifier où la requête est lente, ce qui est certainement une bonne idée.

Une autre suggestion, bien que uou ne dit pas quelle version de DB2 que vous utilisez, ou quelle plate-forme il est sur:

Vous pourriez essayer d'utiliser l'instruction MERGE, qui est l'instruction SQL ANSI pour une mise à jour join (ce qui a été disponible dans DB2 pour Linux/Unix/Windows depuis la version 8.2):

La déclaration de fusion ressemblerait à quelque chose comme (non testé):

merge into tableA a 
    using (select id, col1, col2 from tableB where col3 = 'YY') as b 
    on (a.col1 = b.col1 and a.col2 = b.col2 and a.col3 = 'xx') 
    when matched 
    then update set val1 = 'X', val2 = 'Y' 
2

Je sais ce fil est un peu vieux, mais je voudrais partager ce qui m'est arrivé (spécifique allié aujourd'hui hehe).

Nous étions confrontés au même problème. Mise à jour prenait une éternité à courir! Nous avons donc découvert que la table que nous essayions de mettre à jour était verrouillée. Cependant, aucun message d'erreur n'a été lancé par DB2.

J'espère que j'ai aidé en quelque sorte! Bravo. ~ chamb ~

Questions connexes