Les analyses constantes produisent chacune une seule ligne en mémoire sans colonnes. Le scalaire de calcul supérieur génère une seule ligne avec 3 colonnes
Expr1005 Expr1006 Expr1004
----------- ----------- -----------
NULL NULL 60
Le scalaire inférieur calcule une seule ligne avec 3 colonnes
Expr1008 Expr1009 Expr1007
----------- ----------- -----------
NULL 1048576 10
L'opérateur de concaténation Rassemble ces 2 lignes et affiche les 3 colonnes mais elles sont maintenant renommées
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
La Expr1012
colonne est un ensemble d'indicateurs utilisés en interne pour définir certaines propriétés de recherche pour le moteur de stockage .
Le prochain calcul scalaire produit 2 lignes
Expr1010 Expr1011 Expr1012 Expr1013 Expr1014 Expr1015
----------- ----------- ----------- ----------- ----------- -----------
NULL NULL 60 True 4 16
NULL 1048576 10 False 0 0
Les trois dernières colonnes sont définies comme suit et sont juste utilisées à des fins de tri avant d'être présentées à l'opérateur d'intervalle de fusion
[Expr1013] = Scalar Operator(((4)&[Expr1012]) = (4) AND NULL = [Expr1010]),
[Expr1014] = Scalar Operator((4)&[Expr1012]),
[Expr1015] = Scalar Operator((16)&[Expr1012])
Expr1014
et Expr1015
juste tester si certains bits sont activés dans le drapeau.
Expr1013
semble renvoyer une colonne booléenne true si le bit for 4
est allumé et l' Expr1010
est NULL
.
En essayant d'autres opérateurs de comparaison dans la requête, j'obtiens ces résultats
+----------+----------+----------+-------------+----+----+---+---+---+---+
| Operator | Expr1010 | Expr1011 | Flags (Dec) | Flags (Bin) |
| | | | | 32 | 16 | 8 | 4 | 2 | 1 |
+----------+----------+----------+-------------+----+----+---+---+---+---+
| > | 1048576 | NULL | 6 | 0 | 0 | 0 | 1 | 1 | 0 |
| >= | 1048576 | NULL | 22 | 0 | 1 | 0 | 1 | 1 | 0 |
| <= | NULL | 1048576 | 42 | 1 | 0 | 1 | 0 | 1 | 0 |
| < | NULL | 1048576 | 10 | 0 | 0 | 1 | 0 | 1 | 0 |
| = | 1048576 | 1048576 | 62 | 1 | 1 | 1 | 1 | 1 | 0 |
| IS NULL | NULL | NULL | 60 | 1 | 1 | 1 | 1 | 0 | 0 |
+----------+----------+----------+-------------+----+----+---+---+---+---+
D'où je déduis que le bit 4 signifie "a le début de la plage" (par opposition à non illimité) et le bit 16 signifie que le début de la plage est inclusif.
Ce jeu de résultats à 6 colonnes est émis par l' SORT
opérateur trié par
Expr1013 DESC, Expr1014 ASC, Expr1010 ASC, Expr1015 DESC
. En supposant True
est représenté par 1
et False
par 0
le jeu de résultats précédemment représenté est déjà dans cet ordre.
Sur la base de mes hypothèses précédentes, l'effet net de ce type est de présenter les plages à l'intervalle de fusion dans l'ordre suivant
ORDER BY
HasStartOfRangeAndItIsNullFirst,
HasUnboundedStartOfRangeFirst,
StartOfRange,
StartOfRangeIsInclusiveFirst
L'opérateur d'intervalle de fusion génère 2 lignes
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
Pour chaque ligne émise, une recherche de plage est effectuée
Seek Keys[1]: Start:[dbo].[t].c2 > Scalar Operator([Expr1010]),
End: [dbo].[t].c2 < Scalar Operator([Expr1011])
Il semblerait donc que deux recherches soient effectuées. Un apparemment > NULL AND < NULL
et un > NULL AND < 1048576
. Cependant, les drapeaux transmis semblent modifier cela respectivement IS NULL
et < 1048576
. Espérons que @sqlkiwi puisse clarifier cela et corriger toute inexactitude!
Si vous modifiez légèrement la requête en
select *
from t
where
c2 > 1048576
or c2 = 0
;
Ensuite, le plan semble beaucoup plus simple avec une recherche d'index avec plusieurs prédicats de recherche.
Le plan montre Seek Keys
Start: c2 >= 0, End: c2 <= 0,
Start: c2 > 1048576
L'explication pour laquelle ce plan plus simple ne peut pas être utilisé pour le cas dans l'OP est donnée par SQLKiwi dans les commentaires de l' article de blog lié précédent .
Une recherche d'index avec plusieurs prédicats ne peut pas mélanger différents types de prédicat de comparaison (c'est-à-dire Is
et Eq
dans le cas de l'OP). Il s'agit simplement d'une limitation actuelle du produit (et c'est probablement la raison pour laquelle le test d'égalité dans la dernière requête c2 = 0
est implémenté en utilisant >=
et <=
non pas simplement la recherche d'égalité simple que vous obtenez pour la requête c2 = 0 OR c2 = 1048576
.
62
c'est pour une comparaison d'égalité. Je suppose60
que cela doit signifier qu'au lieu de> AND <
comme indiqué dans le plan, vous obtenez en fait à>= AND <=
moins que ce soit unIS NULL
drapeau explicite peut-être (?) Ou peut-être que le bit2
indique autre chose sans rapport et qu'il60
soit toujours égal à moi quand je le faisset ansi_nulls off
et que je le change ilc2 = null
reste toujours à60
Les analyses constantes sont un moyen pour SQL Server de créer un compartiment dans lequel il va placer quelque chose plus tard dans le plan d'exécution. J'en ai posté une explication plus approfondie ici . Pour comprendre à quoi sert le balayage constant, vous devez approfondir le plan. Dans ce cas, ce sont les opérateurs de calcul scalaire qui sont utilisés pour remplir l'espace créé par l'analyse constante.
Les opérateurs de calcul scalaire sont chargés avec NULL et la valeur 1045876, ils seront donc clairement utilisés avec la jointure en boucle dans le but de filtrer les données.
La partie vraiment cool est que ce plan est Trivial. Cela signifie qu'il a subi un processus d'optimisation minimal. Toutes les opérations mènent à l'intervalle de fusion. Ceci est utilisé pour créer un ensemble minimal d'opérateurs de comparaison pour une recherche d'index ( détails à ce sujet ici ).
L'idée est de se débarrasser des valeurs qui se chevauchent pour pouvoir ensuite extraire les données avec un minimum de passes. Bien qu'il utilise toujours une opération de boucle, vous remarquerez que la boucle s'exécute exactement une fois, ce qui signifie qu'il s'agit en fait d'une analyse.
ADDENDA: Cette dernière phrase est éteinte. Il y a eu deux recherches. J'ai mal lu le plan. Les autres concepts sont les mêmes et l'objectif, les passes minimales, est le même.
la source