2009-09-16 14 views
0

Un de mes anciens collègues a écrit le UPDATE suivant dans le cadre d'un script d'importation de données et il faut près de 15 minutes pour terminer sur une table de 92k lignes.Une mise à jour lente de SQL pourrait utiliser un peu d'aide

UPDATE table 
SET name = (
    SELECT TOP 1 old_name FROM (
     SELECT 
      SUM(r) rev, 
      number, 
      name, 
      intermediate_number, 
      intermediate_name, 
      old_number, 
      old_name 
     FROM table 
     GROUP BY 
      number, 
      name, 
      intermediate_number, 
      intermediate_name, 
      old_number, 
      old_name 
    ) t 
    WHERE t.name = table.name 
    ORDER BY rev DESC 
); 

Je suis sûr qu'il peut être réécrite pour être plus efficace, mais toutes mes tentatives ont échoué, ou pas produit les mêmes résultats.

De plus, aucun index n'est défini sur la table. Suggestions appréciées. Je suis sur Sybase iAnywhere 11 si cela compte.

+1

intermediate_number pourrait utiliser des filatures. – David

Répondre

3

Mettre un index sur OLD_NAME et voir combien de temps il faut que ... est-

En second lieu, dans l'analyse de votre requête, il semble qu'il y ait peut-être un défaut en elle. si vous regardez la version reformatée ci-dessous,

UPDATE table SET 
    name = (SELECT TOP 1 old_name 
      FROM (SELECT SUM(r) rev, number, name, 
        intermediate_number, intermediate_name, 
        old_number, old_name 
        FROM table 
        GROUP BY number, name, intermediate_number, 
         intermediate_name, old_number, old_name) t 
      WHERE t.old_name = table.old_name -- HERE 
      ORDER BY rev DESC); 

La seconde dernière ligne OÙ t.old_name = table.old_name entraînera la sous-requête interne pour avoir seulement des lignes avec t.oldname = à la valeur de la requête externe table.old_name. Donc, peu importe que vous fassiez un Top 1 ou non, puisque toutes les lignes auront la même valeur pour old_name, vous définirez toujours la valeur à exactement ce qu'elle est déjà, non ??

EDIT: (en fonction de l'endroit où le changement de l'article), essayez ceci:

UPDATE table SET 
    name = (SELECT Top 1 old_name 
      FROM table it 
      Where it.name = table.old_name 
      GROUP BY number, intermediate_number, 
         intermediate_name, old_number, old_name 
      Order By SUM(r) Desc); 
+0

Je viens d'éditer, la clause WHERE était erronée, la comparaison est en fait sur la colonne de nom, donc je vais essayer avec un index sur cela. –

+0

Temps d'exécution: 163.707 secondes: D –

0

Je ne suis pas une personne Sybase, mais je le ferais de la manière que vous avez choisi.

psudo Sql

DECLARE @tempTable TABLE --In memory table if possible 

INSERT INTO @tempTable 
    SELECT 
      SUM(r) rev, 
      number, 
      name, 
      intermediate_number, 
      intermediate_name, 
      old_number, 
      old_name   
    FROM table   
    GROUP BY 
      number, 
      name, 
      intermediate_number, 
      intermediate_name, 
      old_number, 
      old_namet 
    ORDER BY rev DESC 


UPDATE table 
    SET name = SELECT TOP 1 old_name FROM @tempTable t WHERE t.old_name = table.old_name 

Cela devrait éliminer votre récursive SELECT