2008-12-09 11 views
1
SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value 
    FROM prodtree_element pe 
    LEFT JOIN prodtree_link pl 
     ON pe.prodtree_element_id = pl.to_prodtree_node_id 
    LEFT JOIN line li 
     ON pe.line_code = li.line_code 
    INNER JOIN attribute_values av 
     ON av.attribute_definition_id = #statusCode# 
    LEFT JOIN attribute_values av2 
     ON pe.prodtree_element_id = av.prodtree_element_id 
    WHERE pe.prodtree_element_func_type <> 'WIZARD' 
     AND pe.prodtree_element_topo_type = 'NODE' 

"# statusCode #" est un identifiant statique qui correspond à un identifiant dans la table de définition d'attribut (disons 22 pour l'argument). Le problème est, la requête a un gros problème de finition dans un délai raisonnable. Le plus gros problème est que j'ai un peu besoin de finir plus tôt, mais le nombre d'enregistrements est énorme et doit être réduit (environ 30 à 50 000). J'ai besoin de données provenant de plusieurs tables, c'est là que ça commence à ralentir. C'est juste une partie de ce dont j'ai besoin, j'ai aussi besoin de toute une autre table de données correspondant à l'actuel "prodtree_elment_id". J'utilise ColdFusion mais l'exécution même de la requête directement dans SQL Server 2005 crée l'attente de 15-30 minutes pour cette requête (si elle se termine même). Existe-t-il un moyen concevable d'accélérer cette requête pour prendre au plus 5 minutes ou moins?Besoin d'accélérer cette requête dans SQL Server

+0

Avez-vous des index? Assurez-vous que les jointures ont des index de couverture. Assurez-vous également que vos jointures ne nécessitent aucun casting implicite. Vous pouvez vérifier cela dans le plan de requête. –

Répondre

9
INNER JOIN attribute_values av 
    ON av.attribute_definition_id = #statusCode# 
LEFT JOIN attribute_values av2 
    ON pe.prodtree_element_id = av.prodtree_element_id 

C'est le problème. Il existe une jointure croisée entre pe et av, suivie d'une jointure externe sur la jointure croisée. Vous avez de la chance, il ne prend que 30 minutes :-)

Je pense que vous voulez ceci:

SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value 
FROM prodtree_element pe 
LEFT JOIN prodtree_link pl 
    ON pe.prodtree_element_id = pl.to_prodtree_node_id 
LEFT JOIN line li 
    ON pe.line_code = li.line_code 
--replacement 
LEFT JOIN 
attribute_values av 
     ON pe.prodtree_element_id = av.prodtree_element_id AND 
     av.attribute_definition_id = #statusCode# 
--end replacement 
WHERE pe.prodtree_element_func_type <> 'WIZARD' 
    AND pe.prodtree_element_topo_type = 'NODE' 
+1

Merci, mon problème était que je ne savais pas que vous pourriez faire un ET dans un JOIN! Maintenant que j'ai ajouté cela au code (ce que je dois faire ailleurs aussi), il a été accéléré plus que significativement. L'AND est la clé des gens! – Organiccat

+0

Est-il nécessaire que ce soit dans la section de jointure? Je mets normalement ce genre de chose dans le WHERE. Est-ce que cela augmente les performances? – Sam

+1

Parce que le filtrage est nécessaire sur attribute_values. Si vous avez ceci dans la clause where, alors vous arrêtez la jointure externe et vous limitez les lignes de prodtree_element à av.attribute_definition_id = x – gbn

0

Sans connaître le DDL c'est très difficile à tester. 30-50K lignes ne devraient prendre que quelques secondes.

Essayez de basculer l'ordre de clause where. Vous devriez probablement avoir cette mise en œuvre

INNER JOIN attribute_values av 
     ON av.attribute_definition_id = #statusCode# 

dans la clause where.

0

La première chose que je suggérerais est que vous l'exécutez à travers l'utilitaire sql optimizer dans le gestionnaire d'entreprise à condition que vous l'ayez installé. Il suggère généralement des index et des choses de ce genre qui pourraient avoir un impact positif sur la vitesse de la requête.

D'autres éléments à prendre en compte seraient la division de la requête. A partir des regards initiaux, il semble que vous lisez tous les éléments du produit qui ont un attribut particulier correspondant à la valeur que vous donnez (ou quelque chose comme ça). Je dirais peut-être:

select * from [bigLongjoin to producttree_element] 
where prodtree_element_id 
in(
select prodtree_element_id from 
    attribute_values where attribute_definition_id = #statusCode#) 

Exécution en chef d'entreprise avec le plan de requête affiché pourrait aussi vous montrer où les goulots d'étranglement sont

+0

fait généralement les choses encore plus lent ... – mson

0

Vous pouvez rechercher des millions d'enregistrements en quelques secondes avec une bonne optimisation. Bien que StingyJack ait raison de ne pas connaître le DDL, l'optimisation de toute requête est difficile. Cependant, les choses à faire lors de l'optimisation d'une requête est de regarder le plan d'exécution. Les boucles imbriquées et autres sont mauvaises. Assurez-vous également que vous êtes entièrement indexé. Vous ne mentionnez rien des index des tables en question. Sans les index 30 - 50k lignes pourraient prendre un certain temps avec autant de jointures.

0

assurez-vous que tous vos identifiants sont des indices aussi si vous pouvez mapper les suivantes:

pe.prodtree_element_func_type <> 'WIZARD' 
     AND pe.prodtree_element_topo_type = 'NODE' 

être quelque chose comme

pe.prodtree_element_func_type_ID <> 1 
      AND pe.prodtree_element_topo_type_ID = 2 

afin de réduire les comparaisons de chaîne qui prend plus de temps pour terminer

0
SELECT pe.prodtree_element_id prodID, pe.prodtree_element_name_s, li.line_name, av2.value 
    FROM prodtree_element pe 
    LEFT JOIN prodtree_link pl 
     ON (pe.prodtree_element_id = pl.to_prodtree_node_id) 
    LEFT JOIN line li 
     ON (pe.line_code = li.line_code) 
    LEFT JOIN attribute_values av2 
     ON (pe.prodtree_element_id IN (SELECT av.prodtree_element_id FROM attribute_values av WHERE av.attribute_definition_id = #statusCode#)) 
    WHERE pe.prodtree_element_func_type <> 'WIZARD' 
     AND pe.prodtree_element_topo_type = 'NODE' 

gbn cloué il je pense. Même si vous restreignez l'INNER JOIN à attribute_values ​​à une valeur spécifique, il n'est toujours pas joint du tout à votre table primaire ou à ses relations. Donc, même si vous obtenez des résultats de la requête, je suppose qu'il y en a trop. En fonction de ce que vous vouliez et de la manière dont vos données se trouvent dans la table attribute_values, sa requête ou la mienne seraient probablement plus rapides.

+0

La clause IN le supprimera – gbn

Questions connexes