2010-05-04 4 views
2

J'ai la requêteplus efficace de se joindre à gauche grande table

select P.peopleID, P.peopleName, ED.DataNumber 
from peopleTable P 
    left outer join ( 
     select PE.peopleID, PE.DataNumber 
     from formElements FE 
      inner join peopleExtra PE on PE.ElementID = FE.FormElementID 
     where FE.FormComponentID = 42 
    ) ED on ED.peopleID = P.peopleID 

suivant (simplifié) Sans la sous-requête cette procédure prend environ 7 secondes, mais avec elle, il faut compter environ 3 minutes. Étant donné que le tableau peopleExtra est plutôt volumineux, existe-t-il un moyen plus efficace d'effectuer cette jointure (à moins de restructurer la base de données)?

Plus de détails:

La partie interne de la sous-requête, par exemple

select PE.peopleID, PE.DataNumber 
     from formElements FE 
      inner join peopleExtra PE on PE.ElementID = FE.FormElementID 
     where FE.FormComponentID = 42 

prend entre < 1 et 5 secondes pour exécuter, et retourne 95k lignes

Il y a 1500 entrées dans le peopleTable.

+0

C'est correct comme sous-requête tant que les utilisateurs sont filtrés de manière significative dans la jointure. Si, après la jointure, il y a un grand nombre de lignes résultantes dans votre sous-requête, il est probablement plus approprié de le reformer en une jointure supplémentaire, comme @Orbman l'a fait. – SqlRyan

Répondre

1

Votre requête est OK, il suffit de créer les indices suivants:

PeopleExtra (PeopleID) INCLUDE (DataNumber, ElementID) 
FormElements (FormComponentID, FormElementID) 

Réécrire la jointure n'est pas nécessaire (optimiseur de SQL Server peut traiter les requêtes imbriquées très bien), mais il peut faire votre requête plus lisible par l'homme.

+0

ces index sont en place, bien que le codeur précédent a bloqué "avec recompiler" dans la procédure. Cela semble être la "solution miracle" où je travaille. On dirait une odeur de code si vous me demandez! – RYFN

+0

Je l'ai marqué comme correct comme il était en effet à faire avec l'optimiseur - il s'est avéré qu'il a été optimisé de manière incorrecte. remaniement du reste de la procédure fixé cela. malheureusement un peu d'un hareng rouge! – RYFN

1

Combien de temps cette sous-requête prend-elle pour s'exécuter toute seule? Si cela prend près de 3 minutes, alors vous devez rendre la sous-requête plus efficace par elle-même - si cela ne prend que quelques secondes, alors c'est l'ensemble de l'instruction qui doit être travaillée.

Y a-t-il des index sur peopleExtra? Spécifiquement, sur cela commence avec ElementID et inclut DataNumber? Je suspecte que le problème est la jointure dans votre sous-requête qui cause le problème.

De plus, pouvez-vous inclure un plan de requête? Lancez SET SHOWPLAN_TEXT ON avant votre requête, puis publiez les résultats ici - cela vous aidera à déterminer ce qui les ralentit.

+0

malheureusement la requête elle-même est de 130 lignes plus long que l'exemple donné, donc je ne peux pas inclure le plan d'exécution réel. C'est certainement la sous-requête qui est le bit lent. J'ai les index spécifiés par Quassnoi. – RYFN

+0

@Zeus: si nous parlons de performance, vous devez spécifier la requête exactement comme elle est. Chacune de ces 130 lignes peut avoir de l'importance. – Quassnoi

+0

@Quassnoi vous pouvez être correct ... J'ai la même jointure dans la procédure d'origine. Sans cela, la procédure prend quelques secondes, avec elle, cela prend quelques minutes. C'est pourquoi j'ai tenté de présenter cet exemple simplifié. J'espérais qu'il y avait quelque chose de bancal avec la syntaxe de jointure :) – RYFN

1

Effectuez une jointure sur la table au lieu d'une sous-requête, ce qui devrait donner au préprocesseur de requête une meilleure liberté pour faire les meilleures jointures.

select p.peopleID, p.peopleName, pe.DataNumber 
from peopleTable p 
left join (
    formElements fe 
    inner join peopleExtra pe on pe.ElementID = fe.FormElementID 
) on pe.peopleID = p.peopleID 
where fe.FormComponentID = 42 
+0

Cette requête filtrera les personnes qui n'ont pas 'FormComponentID = 42'. En outre, l'optimiseur de 'SQL Server' est assez intelligent pour traiter les sous-requêtes sans les réécrire. – Quassnoi