powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / QueryPlan: GetRangeWithMismatchedTypes
11 сообщений из 11, страница 1 из 1
QueryPlan: GetRangeWithMismatchedTypes
    #40078413
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Господа, вроде не пятница, а что то лыжи не едут.

имеем на входе:

Код: sql
1.
2.
3.
declare @d1 datetime = '20210616', @d2 DSOPERDAY = '20210616'
select OperationID from tOperPart with(nolock) where OperDate <= @d1 and ResourceID = 20012759732.
select OperationID from tOperPart with(nolock) where OperDate <= @d2 and ResourceID = 20012759732.



DSOPERDAY это пользовательский тип вида
Код: sql
1.
2.
3.
4.
5.
CREATE TYPE [dbo].[DSOPERDAY] FROM smalldatetime NULL
EXEC [sys].[sp_binddefault]
    @defname = 'ZERO_DATE'
    @objname = '[DSOPERDAY]'
GO



в табличке tOperPart колонка OperDate типа DSOPERDAY.
сиквел об этом прекрасно уведомлен, поэтому строя план для первого стейтмента в батче он применяет специальную оптимизацию что бы выстроить диапазон сканирования исходя из типа колонки

оба запроса возвращают одинаковые результаты в три строки что в принципе и должно быть.
анализируя структуру плана у меня рвет шаблон поскольку я вижу что поведение должно бы было быть другим по сути.

план для всего батча
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.518" Build="13.0.5292.0" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
  <BatchSequence>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="2" StatementEstRows="89.5276" StatementId="2" StatementOptmLevel="TRIVIAL" CardinalityEstimationModelVersion="130" StatementSubTreeCost="0.00338048" StatementText="select OperationID from tOperPart with(nolock) where OperDate &lt;= @d1 and ResourceID = 20012759732." StatementType="SELECT" QueryHash="0x273660F61DC7F47C" QueryPlanHash="0x8C6F4A7E04411A2A" RetrievedFromCache="true" SecurityPolicyApplied="false">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan DegreeOfParallelism="0" NonParallelPlanReason="MaxDOPSetToOne" CachedPlanSize="24" CompileTime="1" CompileCPU="1" CompileMemory="232">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="1600000" EstimatedPagesCached="6400000" EstimatedAvailableDegreeOfParallelism="1" MaxCompileMemory="623934360" />
            <OptimizerStatsUsage>
              <StatisticsInfo Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Statistics="[XAK1tOperPart]" ModificationCount="15342478" SamplingPercent="100" LastUpdate="2021-04-07T04:14:27.24" />
            </OptimizerStatsUsage>
            <TraceFlags IsCompileTime="true">
              <TraceFlag Value="460" Scope="Global" />
              <TraceFlag Value="1222" Scope="Global" />
              <TraceFlag Value="1224" Scope="Global" />
            </TraceFlags>
            <TraceFlags IsCompileTime="false">
              <TraceFlag Value="460" Scope="Global" />
              <TraceFlag Value="1222" Scope="Global" />
              <TraceFlag Value="1224" Scope="Global" />
            </TraceFlags>
            <QueryTimeStats CpuTime="0" ElapsedTime="0" />
            <RelOp AvgRowSize="16" EstimateCPU="0.00025548" EstimateIO="0.003125" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="89.5276" EstimatedRowsRead="89.5276" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.00338048" TableCardinality="496295000">
              <OutputList>
                <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperationID" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="3" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" />
              </RunTimeInformation>
              <NestedLoops Optimized="false">
                <OuterReferences>
                  <ColumnReference Column="Expr1004" />
                  <ColumnReference Column="Expr1005" />
                  <ColumnReference Column="Expr1003" />
                </OuterReferences>
                <RelOp AvgRowSize="19" EstimateCPU="0" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1" LogicalOp="Compute Scalar" NodeId="1" Parallel="false" PhysicalOp="Compute Scalar" EstimatedTotalSubtreeCost="0">
                  <OutputList>
                    <ColumnReference Column="Expr1004" />
                    <ColumnReference Column="Expr1005" />
                    <ColumnReference Column="Expr1003" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="1" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" />
                  </RunTimeInformation>
                  <ComputeScalar>
                    <DefinedValues>
                      <DefinedValue>
                        <ValueVector>
                          <ColumnReference Column="Expr1004" />
                          <ColumnReference Column="Expr1005" />
                          <ColumnReference Column="Expr1003" />
                        </ValueVector>
                        <ScalarOperator ScalarString="GetRangeWithMismatchedTypes(NULL,[@d1],(42))">
                          <Intrinsic FunctionName="GetRangeWithMismatchedTypes">
                            <ScalarOperator>
                              <Const ConstValue="NULL" />
                            </ScalarOperator>
                            <ScalarOperator>
                              <Identifier>
                                <ColumnReference Column="@d1" />
                              </Identifier>
                            </ScalarOperator>
                            <ScalarOperator>
                              <Const ConstValue="(42)" />
                            </ScalarOperator>
                          </Intrinsic>
                        </ScalarOperator>
                      </DefinedValue>
                    </DefinedValues>
                    <RelOp AvgRowSize="0" EstimateCPU="0" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1" LogicalOp="Constant Scan" NodeId="2" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0">
                      <OutputList />
                      <RunTimeInformation>
                        <RunTimeCountersPerThread Thread="0" ActualRows="1" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" />
                      </RunTimeInformation>
                      <ConstantScan />
                    </RelOp>
                  </ComputeScalar>
                </RelOp>
                <RelOp AvgRowSize="16" EstimateCPU="0.00025548" EstimateIO="0.003125" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="89.5276" EstimatedRowsRead="89.5276" LogicalOp="Index Seek" NodeId="3" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.00338048" TableCardinality="496295000">
                  <OutputList>
                    <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperationID" />
                  </OutputList>
                  <RunTimeInformation>
                    <RunTimeCountersPerThread Thread="0" ActualRows="3" ActualRowsRead="3" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" ActualScans="1" ActualLogicalReads="4" ActualPhysicalReads="0" ActualReadAheads="0" ActualLobLogicalReads="0" ActualLobPhysicalReads="0" ActualLobReadAheads="0" />
                  </RunTimeInformation>
                  <IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
                    <DefinedValues>
                      <DefinedValue>
                        <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperationID" />
                      </DefinedValue>
                    </DefinedValues>
                    <Object Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Index="[XAK1tOperPart]" IndexKind="NonClustered" Storage="RowStore" />
                    <SeekPredicates>
                      <SeekPredicateNew>
                        <SeekKeys>
                          <Prefix ScanType="EQ">
                            <RangeColumns>
                              <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="ResourceID" />
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="(20012759732.)">
                                <Const ConstValue="(20012759732.)" />
                              </ScalarOperator>
                            </RangeExpressions>
                          </Prefix>
                          <StartRange ScanType="GT">
                            <RangeColumns>
                              <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1004]">
                                <Identifier>
                                  <ColumnReference Column="Expr1004" />
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </StartRange>
                          <EndRange ScanType="LT">
                            <RangeColumns>
                              <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
                            </RangeColumns>
                            <RangeExpressions>
                              <ScalarOperator ScalarString="[Expr1005]">
                                <Identifier>
                                  <ColumnReference Column="Expr1005" />
                                </Identifier>
                              </ScalarOperator>
                            </RangeExpressions>
                          </EndRange>
                        </SeekKeys>
                      </SeekPredicateNew>
                    </SeekPredicates>
                  </IndexScan>
                </RelOp>
              </NestedLoops>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@d1" ParameterDataType="datetime" ParameterRuntimeValue="'2021-06-16 00:00:00.000'" />
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
    <Batch>
      <Statements>
        <StmtSimple StatementCompId="3" StatementEstRows="89.5276" StatementId="4" StatementOptmLevel="TRIVIAL" CardinalityEstimationModelVersion="130" StatementSubTreeCost="0.00338048" StatementText="select OperationID from tOperPart with(nolock) where OperDate &lt;= @d2 and ResourceID = 20012759732." StatementType="SELECT" QueryHash="0x273660F61DC7F47C" QueryPlanHash="0x7B49ECE5EC336B88" RetrievedFromCache="true" SecurityPolicyApplied="false">
          <StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
          <QueryPlan DegreeOfParallelism="0" NonParallelPlanReason="MaxDOPSetToOne" CachedPlanSize="16" CompileTime="0" CompileCPU="0" CompileMemory="232">
            <MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
            <OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="1600000" EstimatedPagesCached="6400000" EstimatedAvailableDegreeOfParallelism="1" MaxCompileMemory="623934360" />
            <OptimizerStatsUsage>
              <StatisticsInfo Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Statistics="[XAK1tOperPart]" ModificationCount="15342478" SamplingPercent="100" LastUpdate="2021-04-07T04:14:27.24" />
            </OptimizerStatsUsage>
            <TraceFlags IsCompileTime="true">
              <TraceFlag Value="460" Scope="Global" />
              <TraceFlag Value="1222" Scope="Global" />
              <TraceFlag Value="1224" Scope="Global" />
            </TraceFlags>
            <TraceFlags IsCompileTime="false">
              <TraceFlag Value="460" Scope="Global" />
              <TraceFlag Value="1222" Scope="Global" />
              <TraceFlag Value="1224" Scope="Global" />
            </TraceFlags>
            <QueryTimeStats CpuTime="0" ElapsedTime="0" />
            <RelOp AvgRowSize="16" EstimateCPU="0.00025548" EstimateIO="0.003125" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="89.5276" EstimatedRowsRead="89.5276" LogicalOp="Index Seek" NodeId="0" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="0.00338048" TableCardinality="496295000">
              <OutputList>
                <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperationID" />
              </OutputList>
              <RunTimeInformation>
                <RunTimeCountersPerThread Thread="0" ActualRows="3" ActualRowsRead="3" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" ActualScans="1" ActualLogicalReads="4" ActualPhysicalReads="0" ActualReadAheads="0" ActualLobLogicalReads="0" ActualLobPhysicalReads="0" ActualLobReadAheads="0" />
              </RunTimeInformation>
              <IndexScan Ordered="true" ScanDirection="FORWARD" ForcedIndex="false" ForceSeek="false" ForceScan="false" NoExpandHint="false" Storage="RowStore">
                <DefinedValues>
                  <DefinedValue>
                    <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperationID" />
                  </DefinedValue>
                </DefinedValues>
                <Object Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Index="[XAK1tOperPart]" IndexKind="NonClustered" Storage="RowStore" />
                <SeekPredicates>
                  <SeekPredicateNew>
                    <SeekKeys>
                      <Prefix ScanType="EQ">
                        <RangeColumns>
                          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="ResourceID" />
                        </RangeColumns>
                        <RangeExpressions>
                          <ScalarOperator ScalarString="(20012759732.)">
                            <Const ConstValue="(20012759732.)" />
                          </ScalarOperator>
                        </RangeExpressions>
                      </Prefix>
                      <EndRange ScanType="LE">
                        <RangeColumns>
                          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
                        </RangeColumns>
                        <RangeExpressions>
                          <ScalarOperator ScalarString="[@d2]">
                            <Identifier>
                              <ColumnReference Column="@d2" />
                            </Identifier>
                          </ScalarOperator>
                        </RangeExpressions>
                      </EndRange>
                    </SeekKeys>
                  </SeekPredicateNew>
                </SeekPredicates>
              </IndexScan>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@d2" ParameterDataType="smalldatetime" ParameterRuntimeValue="'2021-06-16 00:00:00.000'" />
            </ParameterList>
          </QueryPlan>
        </StmtSimple>
      </Statements>
    </Batch>
  </BatchSequence>
</ShowPlanXML>





я не очень понимаю как так получается, судя по плану для первого запроса оптимизатор использует функцию получения диапазона с приведения типов для задания диапазона сканирования.
но что примечательно дальше по плану для сканирования индекса он задает диапазон вида:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
 <StartRange ScanType="GT">
    <RangeColumns>
       <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
    </RangeColumns>
    <RangeExpressions>
        <ScalarOperator ScalarString="[Expr1004]">
             <Identifier>
                  <ColumnReference Column="Expr1004" />
             </Identifier>
        </ScalarOperator>
    </RangeExpressions>
</StartRange>
<EndRange ScanType="LT">
    <RangeColumns>
         <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
    </RangeColumns>
    <RangeExpressions>
        <ScalarOperator ScalarString="[Expr1005]">
            <Identifier>
                 <ColumnReference Column="Expr1005" />
            </Identifier>
         </ScalarOperator>
 </RangeExpressions>



для вычисления внутренней функции GetRangeWithMismatchedTypes(NULL,[@d1],(42))
получается у нас данная конструкция была бы эквивалентом
псеводкод
Код: sql
1.
2.
declare @expr1004 smalldatetime = null, @expr1005 smalldatetime = '20210616', @resourceID numeric(15, 0) = 20012759732.;
select OperationID from [dbo].[tOperPart] where [resourceID] = @resourceID and [OperDate] > @expr1004 and [OperDate] < @expr1005




но это не так потому что предикат у нас меньше-равно в запросе.
может ли получаться так что внутренняя функция меняет значение для Expr1005 и оно становится не 20160616 а 20160617? иначе я не понимаю как в плане присутствуют диапазоны с типом ScanType = GT/LT а результаты запросов совпадают?
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078419
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
add:

кстати для запроса с литералом он выстраивает план с типом сканирования диапазона правильного типа:

Код: sql
1.
select OperationID from tOperPart with(nolock) where OperDate <= '20210616' and ResourceID = 20012759732.



Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
              <EndRange ScanType="LE">
                        <RangeColumns>
                          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
                        </RangeColumns>
                        <RangeExpressions>
                          <ScalarOperator ScalarString="CONVERT_IMPLICIT(smalldatetime,[@1],0)">
                            <Identifier>
                              <ColumnReference Column="ConstExpr1003">
                                <ScalarOperator>
                                  <Convert DataType="smalldatetime" Style="0" Implicit="true">
                                    <ScalarOperator>
                                      <Identifier>
                                        <ColumnReference Column="@1" />
                                      </Identifier>
                                    </ScalarOperator>
                                  </Convert>
                                </ScalarOperator>
                              </ColumnReference>
                            </Identifier>
                          </ScalarOperator>
                        </RangeExpressions>
                      </EndRange>
                    </SeekKeys>
                  </SeekPredicateNew>
                </SeekPredicates>
              </IndexScan>
            </RelOp>
            <ParameterList>
              <ColumnReference Column="@2" ParameterDataType="numeric(11,0)" ParameterCompiledValue="(20012759732.)" ParameterRuntimeValue="(20012759732.)" />
              <ColumnReference Column="@1" ParameterDataType="varchar(8000)" ParameterCompiledValue="'20210616'" ParameterRuntimeValue="'20210616'" />



и тут у меня вопросов к нему нет, а вот при использовании GetRangeWithMismatchedTypes чето "нито"
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078509
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff,

Честно говоря, особо не вникал.
У GetRangeWithMismatchedTypes третий параметр - набор флагов. Описан тут - https://sqlserverfast.com/epr/index-seek/#DynSeekRange
В вашем случае значение флагов 42 (двоичное 101010), т.е. биты 2 и 4 установлены.
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078516
Владислав Колосов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff,

по идее, не должно влиять на план, но если попробовать where OperDate <= CAST(@d2 AS DATETIME)?
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078578
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владислав Колосов,

оно на план по сути дела не влияет и вот это меня больше всего смущает.

если дословно интерпретировать план получается что написанно взять такие то строки где колонка даты в интервале (~; '20210616')

хотя если смотреть условие самой квери то там по сути условие (~; '20210616'], и работает то главное именно так как нужно, но почему он в ScanType ставит LT вместо LE мне непонятно.

invm,
да посмотрел флаги немного странно написано, если считать по статье на 42 выставлены 2,4,6 биты
тут чето мутно написано, он их местами что ли меняет в зависимоти от флагов?

GetRangeWithMismatchedTypes(NULL,[@d1],(42))
у нас должно получаться условие [dbo].[tOperPart] where [OperDate] > Expr1 and [OperDate] < Expr2

если мы считаем что выставлены биты 2,4,6

Bit-2 (4): When this bit is on, the value in Expr1 represents the end of the interval. When this bit is off, the interval has no end. The latter is e.g. the case for an interval defined by just a single > or >= comparison.
Bit-4 (16): Only used when bit-2 is on. When this bit is on, the value in Expr1 is included in the interval. When it is off, the value in Expr1 is not included.
Bit-6 (64) and bit-7 (128): Appear to be unused.


получается что кондишн будет таким:
[dbo].[tOperPart] where [OperDate] >= NULL and [OperDate] < @date
что не особо сходится с запросом

нумерация может быть с нуля тогда возможно выставлены 1,3,5 что больше походит на правду 42 (2 + 8 + 32)

Bit-1 (2) : Represents the ANSI_NULLS setting for equality comparisons with NULL. This bit is set to 0 when ANSI_NULLS is off, but also when an IS NULL condition is internally converted to an equality comparison for a dynamic seek range.
Bit-3 (8) : When this bit is on, the value in Expr2 represents the start of the interval. When this bit is off, the interval has no start. The latter is e.g. the case for an interval defined by just a single < or <= comparison.
Bit-5 (32) : Only used when bit-3 is on. When this bit is on, the value in Expr2 is included in the interval. When it is off, the value in Expr2 is not included.

тогда конечный кондишн будет таким:
[dbo].[tOperPart] where [OperDate] > NULL and [OperDate] <= @date
если читать по последней фразе, но я не понимаю как интерпретировать "When this bit is on, the value in Expr2 represents the start of the interval."

это равносильно
[dbo].[tOperPart] where [OperDate] >= Expr2 (@date) and [OperDate] < Expr1 (null)?

или это равносильно StartInterval в QueryPlan?
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
<StartRange ScanType="GT">
      <RangeColumns>
            <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Column="OperDate" />
       </RangeColumns>
         <RangeExpressions>
              <ScalarOperator ScalarString="[Expr2]">
                     <Identifier>
                          <ColumnReference Column="Expr2" />
                       </Identifier>
               </ScalarOperator>
       </RangeExpressions>
</StartRange>



но опять тогда какая то джигурда выходит.
вообщем по описанию я не очень понимаю как выйти на ситуацию когда Expr2 будет @date и в каком месте в плане он будет показан так что бы выполнялось условие что скан строк идет до даты параметра @date включительно
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078590
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff,

Можно попробовать посмотреть какие значения в Expr...
https://www.sqlshack.com/query-trace-column-values/
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078607
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

да, спасибо убедился.

у него получается что expr1040 - null; expr1041 - '20210616', expr1039 - флаги в 42
соответствует тому что он рисует в плане:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
<DefinedValues>
  <DefinedValue>
    <ValueVector>
      <ColumnReference Column="Expr1040" />
      <ColumnReference Column="Expr1041" />
      <ColumnReference Column="Expr1039" />
    </ValueVector>
    <ScalarOperator ScalarString="GetRangeWithMismatchedTypes(NULL,'2021-06-16 00:00:00.000',(42))">
      <Intrinsic FunctionName="GetRangeWithMismatchedTypes">
        <ScalarOperator>
          <Const ConstValue="NULL" />
        </ScalarOperator>
        <ScalarOperator>
          <Const ConstValue="'2021-06-16 00:00:00.000'" />
        </ScalarOperator>
        <ScalarOperator>
          <Const ConstValue="(42)" />
        </ScalarOperator>
      </Intrinsic>
    </ScalarOperator>
  </DefinedValue>
</DefinedValues>



но в плане так же в SeekPredicate попрежнему


Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
<SeekPredicates>
  <SeekPredicateNew>
    <SeekKeys>
      <Prefix ScanType="EQ">
        <RangeColumns>
          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Alias="[op]" Column="ResourceID" />
        </RangeColumns>
        <RangeExpressions>
          <ScalarOperator ScalarString="(20012759732.)">
            <Const ConstValue="(20012759732.)" />
          </ScalarOperator>
        </RangeExpressions>
      </Prefix>
      <StartRange ScanType="GT">
        <RangeColumns>
          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Alias="[op]" Column="OperDate" />
        </RangeColumns>
        <RangeExpressions>
          <ScalarOperator ScalarString="[Expr1040]">
            <Identifier>
              <ColumnReference Column="Expr1040" />
            </Identifier>
          </ScalarOperator>
        </RangeExpressions>
      </StartRange>
      <EndRange ScanType="LT">
        <RangeColumns>
          <ColumnReference Database="[somedb]" Schema="[dbo]" Table="[tOperPart]" Alias="[op]" Column="OperDate" />
        </RangeColumns>
        <RangeExpressions>
          <ScalarOperator ScalarString="[Expr1041]">
            <Identifier>
              <ColumnReference Column="Expr1041" />
            </Identifier>
          </ScalarOperator>
        </RangeExpressions>
      </EndRange>
    </SeekKeys>
  </SeekPredicateNew>
</SeekPredicates>




ну и при этом
Код: xml
1.
 <RunTimeCountersPerThread Thread="0" "ActualRows="3" Batches="0" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0" ActualScans="1" ActualLogicalReads="4" ActualPhysicalReads="0" ActualReadAheads="0" ActualLobLogicalReads="0" ActualLobPhysicalReads="0" ActualLobReadAheads="0" ActualRowsRead="3" ActualEndOfScans="1" ActualExecutions="1">



хотя строк для [operDate] < '20210616' рельно нет. все в дате '20210616'

по-видимому где то внутри все таки используется значение колонки expr1039, но в плане его реально не видно.
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078614
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
напомните мне такую вещь, я все это действо с разбором полетов затеял потому что изначально разбирал несколько иной случай, но в итоге вылез на эту особенность в плане.

у нас физ.оператор соединения NL прекратит обработку левого входа если в правом ничего не найдет?
допустим у нас левый вход заведомо вернет 3 строки, в правом заведомо ничего не вернется, обязан ли левый вход быть выбран полностью?
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078637
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff
допустим у нас левый вход заведомо вернет 3 строки, в правом заведомо ничего не вернется, обязан ли левый вход быть выбран полностью?
Не обязан.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
declare @t1 table (id int, s char(8000) null);
insert into @t1
 (id)
values
 (1), (2), (3);

declare @t2 table (id int, v int not null);
insert into @t2
 (id, v)
values
 (1, 0), (2, 0), (3, 0);

set statistics xml, io on;
 
select
 *
from
 @t1 a join
 @t2 b on b.id = a.id and b.v is null
option
 (loop join);

set statistics xml, io off;

В этом примере даже к таблицам нет обращений. Все задавлено уже при компиляции.
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078653
felix_ff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
invm,

ну да, я это тоже заметил. у меня просто был несколько специфичный пример который я за уши притянул в ходе тестов.

приведу его для наглядности
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
drop table if exists #r, #o, #k;

create table #k (
      [key] int index ix clustered,
      [date] datetime
)
insert into #k values (1000, '20210616')

create table #o (
      [id] int index ix clustered,
      [date] datetime,
      [key] int,
      [sign] smallint,
      [value] money,
      index ix2 ([key], [date], [sign])
);
insert into #o values (1, '20210616', 1000, 1, 100)
insert into #o values (2, '20210616', 1000, 1, 50)
insert into #o values (3, '20210616', 1000, 1, 50)

create table #r (
      [key] int,
      [date] datetime,
      [value] money,
      index ix clustered ([key], [date] desc)
);

declare @key int = 1000, @d datetime = '20210616';

set statistics xml on;
with x as (
    select [key], [date] from #k where [key] = @key
),
r0 as (
     select top(1) [value], dateadd(dd, 1, [date]) as [date] from #r where [key] = @key and [date] <= @d order by [date] desc
),
r1 as (
     select
           sum(o.[value] * o.[sign]) as value
     from #o o
     where o.[key] = @key 
       and o.[date] >= (select [date] from r0) --isnull((select [date] from r0), (select [date] from x))
)
select 
      x.[key],
      r0.value,
      r1.value
from x
    outer apply r0
    outer apply r1
option (force order);

set statistics xml off



тут интересное как раз поведение вырисовывается если форсировать порядок соединений.
он начинает сканирование индекса на #o, но после того как берет первую строку видит что правый вход нихрена не дал и дальше уже не сканирует.

это мне немного глаза приоткрыло :)

но в целом ситуация понятна.
с основной своей проблемой я разобрался там хреновая логика была, но вот вопросы к интервалам сканирования в планах пока остались.
...
Рейтинг: 0 / 0
QueryPlan: GetRangeWithMismatchedTypes
    #40078672
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
felix_ff
он начинает сканирование индекса на #o, но после того как берет первую строку видит что правый вход нихрена не дал и дальше уже не сканирует.
Правильно.
Там же на правом входе инвариантный подзапрос. Если он ничего не вернул, то нет смысла далее крутить NL.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / QueryPlan: GetRangeWithMismatchedTypes
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]