web-dev-qa-db-fra.com

Dans quel ordre les requêtes et sous-requêtes sont-elles exécutées par le moteur SQL?

Bonjour j'ai fait un test SQL et douteux/curieux sur une question:

Dans quelle séquence les requêtes et sous-requêtes sont-elles exécutées par le moteur SQL?

les réponses étaient

  1. requête principale -> sous-requête -> sous-sous-requête et ainsi de suite
  2. sous-sous-requête -> sous-requête -> requête principale
  3. toute la requête est interprétée en même temps
  4. Il n'y a pas de séquence d'interprétation fixe, l'analyseur de requête prend une décision à la volée

J'ai choisi la dernière réponse (en supposant simplement qu'elle est la plus fiable par rapport aux autres). Maintenant la curiosité:

où puis-je lire à ce sujet et brièvement quel est le mécanisme sous tout cela?

Je vous remercie.

30
Igor

L'option 4 est proche.

SQL est déclaratif : vous dites à l'optimiseur de requête ce que vous voulez et cela fonctionne le mieux (sous réserve de temps/"coût", etc.). Cela peut varier pour des requêtes et des tables extérieurement identiques en fonction des statistiques, de la distribution des données, du nombre de lignes, du parallélisme et Dieu sait quoi d'autre.

Cela signifie qu'il n'y a pas d'ordre fixe. Mais ce n'est pas tout à fait "à la volée"

Même avec des serveurs, des schémas, des requêtes et des données identiques, j'ai vu des plans d'exécution différer

17
gbn

Je pense que la réponse 4 est correcte. Il y a quelques considérations:

type de sous-requête - est-elle corrélée ou non? Considérer:

SELECT *
FROM   t1
WHERE  id IN (
             SELECT id
             FROM   t2
            )

Ici, la sous-requête n'est pas corrélée à la requête externe. Si le nombre de valeurs dans t2.id est petit par rapport à t1.id, il est probablement plus efficace d'exécuter d'abord la sous-requête et de conserver le résultat en mémoire, puis d'analyser t1 ou un index sur t1.id, en le comparant à les valeurs mises en cache.

Mais si la requête est:

SELECT *
FROM   t1
WHERE  id IN (
             SELECT id
             FROM   t2
             WHERE  t2.type = t1.type
            )

ici la sous-requête est corrélée - il n'y a aucun moyen de calculer la sous-requête à moins que t1.type soit connu. Étant donné que la valeur de t1.type peut varier pour chaque ligne de la requête externe, cette sous-requête peut être exécutée une fois pour chaque ligne de la requête externe.

Là encore, le SGBDR peut être vraiment intelligent et se rendre compte qu'il n'y a que quelques valeurs possibles pour t2.type. Dans ce cas, il peut toujours utiliser l'approche utilisée pour la sous-requête non corrélée s'il peut deviner que le coût d'exécution de la sous-requête une fois sera moins cher que de le faire pour chaque ligne.

25
Roland Bouman

Si vous souhaitez obtenir des informations sur ces sujets, procurez-vous une copie de Inside SQL Server 2008: T-SQL Querying. Il contient deux chapitres dédiés sur la façon dont les requêtes sont traitées logiquement et physiquement dans SQL Server.

1
Frank Kalis

Le moteur SQL essaie d'optimiser l'ordre dans lequel les (sous) requêtes sont exécutées. La partie qui décide de cela s'appelle un optimiseur de requête. L'optimiseur de requêtes sait combien de lignes se trouvent dans chaque table, quelles tables ont des index et sur quels champs. Il utilise ces informations pour décider quelle partie exécuter en premier.

1
Stephan Eggermont

Cela dépend généralement de votre SGBD, mais ... Je pense que la deuxième réponse est plus plausible. La requête principale ne peut généralement pas être calculée sans les résultats de la sous-requête.

0
Adelf