Ordre de traitement SQL Server Join / where

18

Après avoir lu la requête Slow SQL, je ne sais pas comment l'optimiser , cela m'a fait penser aux performances générales des requêtes. Certes, nous avons besoin que les résultats de la première table (lorsque d'autres tables sont jointes) soient aussi petits que possible avant de se joindre (jointures internes pour cette question) afin de rendre nos requêtes un tout petit peu plus rapides.

Exemple, devrait-il:

SELECT *
FROM   ( SELECT * FROM table1 WHERE col = @val ) t
INNER JOIN table2 ON col = col2

Soyez meilleur / plus rapide que:

SELECT *
FROM table1
INNER JOIN table2 ON col = col2
WHERE table1.col = @val

Ma théorie est la suivante (ce n'est peut-être pas la mise en œuvre correcte, j'essaie de me souvenir d'un livre interne de SQL Server 2008 que j'ai lu (MSFT Press)):

  1. Le processeur de requêtes obtient d'abord la table de gauche (table1)
  2. Joint la deuxième table (table2) et forme un produit cartésien avant de filtrer les lignes nécessaires (le cas échéant)
  3. Exécute ensuite les clauses WHERE, ORDER BY, GROUP BY, HAVING avec la dernière instruction SEELCT.

Donc, si dans l'instruction # 1 ci-dessus, la table est plus petite, le moteur SQL a moins de travail à faire lors de la formation des produits cartésiens. Ensuite, lorsque vous atteignez l'instruction where, vous disposez d'un jeu de résultats réduit à partir duquel filtrer en mémoire.

Je pourrais être si loin de la marque que c'est irréel. Comme je l'ai dit, c'est une théorie.

Tes pensées?

Remarque : Je viens juste de penser à cette question et je n'ai pas encore eu l'occasion de faire des tests moi-même.

Note 2 : Tagué comme SQL Server car je ne sais rien de l'implémentation de MySql etc. N'hésitez pas à répondre / commenter quand même

Stuart Blackler
la source

Réponses:

15

Le traitement logique d'une requête est sur MSDN (écrit par l'équipe Microsoft SQL Server, pas par des tiers)

1. FROM
2. ON
3. JOIN
4. WHERE
5. GROUP BY
6. WITH CUBE or WITH ROLLUP
7. HAVING
8. SELECT
9. DISTINCT
10. ORDER BY
11. TOP

Une table dérivée suit cela, puis la requête externe recommence etc etc

C'est logique cependant: pas réel . Peu importe comment SQL Server le fait, ces sémantiques sont honorées à la lettre . Le "réel" est déterminé par l'Optimiseur de Requête (QO) et vous évitez le produit Cartesion intermédiaire que vous avez mentionné.

Il convient de mentionner que SQL est déclaratif: vous dites "quoi" pas "comment" comme vous le feriez pour une programmation procédurale / impérative (Java, .net). Donc, dire "cela se produit avant cela" est faux dans de nombreux cas (par exemple, supposition de courts-circuits ou ordre de L à R O WH)

Dans votre cas ci-dessus, le QO générera le même plan, quelle que soit sa structure, car il s'agit d'une simple requête.

Cependant, le QO est basé sur les coûts et pour une requête complexe, il peut prendre 2 semaines pour générer le plan idéal. Il fait donc "assez bien", ce qui n'est pas le cas.

Ainsi, votre premier cas peut aider l'optimiseur à trouver un meilleur plan car l'ordre de traitement logique est différent pour les 2 requêtes. Mais ce n'est peut-être pas le cas.

J'ai utilisé cette astuce sur SQL Server 2000 pour obtenir une amélioration des performances de vitesse 60x sur les requêtes de rapports. À mesure que le QO améliore la version en version, il améliore ces choses.

Et le livre que vous avez mentionné: il y a un différend à ce sujet
Voir SO et les liens suivants: /programming//q/3270338/27535

gbn
la source
6

Une requête SQL n'est pas de nature procédurale, il n'y a pas de traitement de haut en bas des opérateurs de jointure. L'ordre des tables dans vos exemples de requêtes n'a aucune influence sur le plan d'exécution car ils sont logiquement équivalents et généreront exactement le même plan.

Vous avez en quelque sorte évalué deux des options que l' optimiseur de requêtes peut envisager lors de la génération d'un plan pour cette requête. Le principal facteur qui influence le choix du plan est les statistiques des tables impliquées et les coûts associés aux choix des opérateurs dans tous les plans candidats.

Une jointure à deux tables très simple, comme votre exemple, peut être satisfaite par l'un des centaines de plans d'exécution différents. L'optimiseur décide quelle sera la meilleure façon de répondre à votre requête en comparant les coûts de ces plans.

Il se trompe parfois et vous pouvez l'aider à faire de meilleurs choix grâce à une indexation améliorée, à la mise à jour des statistiques et à l'application d'indices. Dans de très rares cas, vous souhaiterez peut-être forcer l'ordre d'exécution en utilisant l'indicateur FORCE ORDER, mais cela doit être utilisé avec parcimonie. C'est un marteau pour casser un écrou, l'optimiseur peut généralement être incité à générer de meilleurs plans en lui fournissant de meilleures informations.

Mark Storey-Smith
la source