2008-09-05 6 views
4

Quelqu'un peut-il expliquer ce comportement ou comment le contourner?Requête SQL lente en raison de la jointure interne et gauche?

Si vous exécutez cette requête:

select * 
from TblA 
left join freetexttable (TblB, *, 'query') on TblA.ID = [Key] 
inner join DifferentDbCatalog.dbo.TblC on TblA.ID = TblC.TblAID 

Il sera très très lent.

Si vous modifiez cette requête pour utiliser deux jointures internes au lieu d'une jointure à gauche, ce sera très rapide. Si vous le changez pour utiliser deux jointures à gauche au lieu d'une jointure interne, ce sera très rapide.

Vous pouvez observer ce même comportement si vous utilisez également une variable de table SQL à la place du fichier freetexttable. Le problème de performance se pose chaque fois que vous avez une variable de table (ou freetexttable) et une table dans un catalogue de base de données différent où l'un est dans une jointure interne et l'autre dans une jointure à gauche.

Est-ce que quelqu'un sait pourquoi c'est lent, ou comment l'accélérer?

Répondre

0

Indexez le champ que vous utilisez pour effectuer la jointure. Une bonne règle est d'attribuer un index à tout foreign ou candidate keys communément référencé.

3

En règle générale, activez l'option «Afficher le plan d'exécution réel», puis examinez de près les causes du ralentissement. (passez votre souris sur chaque jointure pour voir les détails) Vous devez vous assurer que vous obtenez une recherche d'index et non une analyse de table.

Je suppose que ce qui se passe est que SQL est obligé de tout tirer d'une table dans la mémoire afin de faire l'une des jointures. Parfois, inverser l'ordre dans lequel vous rejoignez les tables aidera aussi les choses.

7

Une règle générale est que les jointures externes provoque le nombre de lignes dans un jeu de résultats à augmentation, tandis que jointures internes provoquent le nombre de lignes dans un jeu de résultats à diminution. Bien sûr, il y a beaucoup de scénarios où le contraire est également vrai, mais c'est plus susceptible de fonctionner de cette façon que non. Ce que vous voulez faire pour la performance est de garder la taille de l'ensemble de résultats (jeu de travail) aussi petite que possible le plus longtemps possible. Comme les deux jointures correspondent à la première table, la modification de l'ordre n'affectera pas la précision des résultats. Par conséquent, vous voudrez probablement faire l'INNER JOIN avant LEFT JOIN:

SELECT * 
FROM TblA 
INNER JOIN DifferentDbCatalog.dbo.TblC on TblA.ID = TblC.TblAID 
LEFT JOIN freetexttable (TblB, *, 'query') on TblA.ID = [Key] 

En pratique, l'optimiseur de requêtes devrait être assez intelligent pour compiler d'utiliser l'option plus rapide, quelle que soit vous ordre spécifié pour les jointures. Cependant, il est bon de prétendre que vous avez un optimiseur de requête bête et que les opérations de requête se déroulent dans l'ordre. Cela permet aux futurs responsables de repérer les erreurs ou les hypothèses potentielles concernant la nature des tables. Parce que l'optimiseur devrait réécrire des choses, ceci n'est probablement pas assez bon pour expliquer complètement le comportement que vous voyez, donc vous voudrez toujours examiner le plan d'exécution utilisé pour chaque requête, et probablement ajoutez un index comme suggéré plus tôt. C'est toujours un bon principe à apprendre, cependant.

0

La mise à freetexttable(TblB, *, 'query') dans une table temporaire peut aider si elle est répétée dans le plan d'exécution.

Questions connexes