Question Dans quelle séquence 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 à propos d'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 primaire -> sous requête -> sous sous requête et ainsi de suite
  2. sous sous requête -> sous requête -> prime requête
  3. la requête entière 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êtes prend une décision à la volée

J'ai choisi la dernière réponse (en supposant que ce soit le plus fiable par rapport aux autres). Maintenant la curiosité:

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

Je vous remercie.


23
2018-02-14 22:52


origine


Réponses:


L'option 4 est proche.

SQL est déclaratif: vous dites à l'optimiseur de requêtes ce que vous voulez et cela fonctionne de la meilleure façon (sous réserve de temps / "coût", etc.). Cela peut varier pour des requêtes et des tableaux identiques selon les statistiques, la distribution des données, le nombre de lignes, le 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, les plans d'exécution diffèrent


14
2018-02-15 04:56



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

type de sous-requête - est-ce corrélé 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 faible 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, correspondant à 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 sauf si t1.type est connu. Comme 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 très intelligent et réaliser qu’il n’ya 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 si elle peut deviner que le coût d'exécution de la sous-requête une fois sera moins cher que le faire pour chaque ligne.


23
2018-02-14 23:10



Le moteur SQL tente d'optimiser l'ordre dans lequel les requêtes (sous) 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 dans quels champs. Il utilise ces informations pour décider de la partie à exécuter en premier.


1
2018-02-14 23:03



Si vous voulez lire quelque chose sur ces sujets, obtenez une copie d'Inside SQL Server 2008: T-SQL Querying. Il comporte deux chapitres dédiés sur la manière dont les requêtes sont traitées logiquement et physiquement dans SQL Server.


1
2018-02-15 09:37



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 résultats de sous-requête.


0
2018-02-14 23:01