Każde skanowanie ciągłe tworzy pojedynczy wiersz w pamięci bez kolumn. Górny obliczeniowy skalar wyprowadza pojedynczy wiersz z 3 kolumnami
Expr1005 Expr1006 Expr1004
----------- ----------- -----------
NULL NULL 60
Dolny obliczeniowy skalar wyprowadza pojedynczy wiersz z 3 kolumnami
Expr1008 Expr1009 Expr1007
----------- ----------- -----------
NULL 1048576 10
Operator konkatenacji Łączy te 2 rzędy razem i wyprowadza 3 kolumny, ale ich nazwy zostały zmienione
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
Expr1012
Kolumna jest zestaw flag używanych wewnętrznie definiować pewne poszukiwania właściwości Storage Engine .
Następny oblicz skalar wzdłuż wyjść 2 wiersze
Expr1010 Expr1011 Expr1012 Expr1013 Expr1014 Expr1015
----------- ----------- ----------- ----------- ----------- -----------
NULL NULL 60 True 4 16
NULL 1048576 10 False 0 0
Ostatnie trzy kolumny są zdefiniowane w następujący sposób i są używane do celów sortowania przed przedstawieniem ich operatorowi interwału scalania
[Expr1013] = Scalar Operator(((4)&[Expr1012]) = (4) AND NULL = [Expr1010]),
[Expr1014] = Scalar Operator((4)&[Expr1012]),
[Expr1015] = Scalar Operator((16)&[Expr1012])
Expr1014
i Expr1015
po prostu sprawdź, czy niektóre bity są włączone na fladze.
Expr1013
wydaje się zwracać wartość logiczną true, jeśli oba bity for 4
są włączone i Expr1010
są NULL
.
Po wypróbowaniu innych operatorów porównania w zapytaniu uzyskuję te wyniki
+----------+----------+----------+-------------+----+----+---+---+---+---+
| 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 |
+----------+----------+----------+-------------+----+----+---+---+---+---+
Z czego wywnioskowałem, że bit 4 oznacza „Ma początek zakresu” (w przeciwieństwie do braku ograniczeń), a bit 16 oznacza, że początek zakresu jest włącznie.
Ten 6-kolumnowy zestaw wyników jest emitowany przez SORT
operatora posortowanego według
Expr1013 DESC, Expr1014 ASC, Expr1010 ASC, Expr1015 DESC
. Zakładając, że True
jest reprezentowany przez 1
i False
przez 0
poprzednio przedstawionego wynikowego jest już w tej kolejności.
Opierając się na moich wcześniejszych założeniach, efektem netto tego rodzaju jest przedstawienie zakresów dla interwału scalania w następującej kolejności
ORDER BY
HasStartOfRangeAndItIsNullFirst,
HasUnboundedStartOfRangeFirst,
StartOfRange,
StartOfRangeIsInclusiveFirst
Operator interwału scalania wyprowadza 2 rzędy
Expr1010 Expr1011 Expr1012
----------- ----------- -----------
NULL NULL 60
NULL 1048576 10
Dla każdego emitowanego wiersza przeprowadzane jest wyszukiwanie zakresu
Seek Keys[1]: Start:[dbo].[t].c2 > Scalar Operator([Expr1010]),
End: [dbo].[t].c2 < Scalar Operator([Expr1011])
Wygląda na to, że wykonywane są dwa wyszukiwania. Jeden najwyraźniej > NULL AND < NULL
jeden > NULL AND < 1048576
. Jednak przekazywane flagi wydają się odpowiednio modyfikować to IS NULL
i < 1048576
. Ufnie @sqlkiwi może to wyjaśnić i naprawić wszelkie nieścisłości!
Jeśli nieznacznie zmienisz zapytanie na
select *
from t
where
c2 > 1048576
or c2 = 0
;
Wówczas plan wygląda na znacznie prostszy z wyszukiwaniem indeksu z wieloma predykatami wyszukiwania.
Plan pokazuje Seek Keys
Start: c2 >= 0, End: c2 <= 0,
Start: c2 > 1048576
Wyjaśnienie, dlaczego ten prostszy plan nie może być użyty w sprawie w OP, zostało podane przez SQLKiwi w komentarzach do wcześniejszego linku na blogu .
Indeks szukać z wieloma predykaty nie można mieszać różne rodzaje porównania orzecznika (tzn. Is
, A Eq
w przypadku, w PO). Jest to po prostu ograniczenie prądu produktu (i jest przypuszczalnie dlatego test równości w ostatnim zapytaniu c2 = 0
jest realizowany przy użyciu >=
i <=
raczej niż tylko prostym równości szukać masz dla zapytania c2 = 0 OR c2 = 1048576
.