이 문제를 발견했을 때 다른 것을 연구하고있었습니다. 몇 가지 데이터가 포함 된 테스트 테이블을 생성하고 다른 쿼리를 실행하여 쿼리 작성 방법이 실행 계획에 어떤 영향을 미치는지 알아 냈습니다. 무작위 테스트 데이터를 생성하는 데 사용한 스크립트는 다음과 같습니다.
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('t') AND type in (N'U'))
DROP TABLE t
GO
CREATE TABLE t
(
c1 int IDENTITY(1,1) NOT NULL
,c2 int NULL
)
GO
insert into t
select top 1000000 a from
(select t1.number*2048 + t2.number a, newid() b
from [master]..spt_values t1
cross join [master]..spt_values t2
where t1.[type] = 'P' and t2.[type] = 'P') a
order by b
GO
update t set c2 = null
where c2 < 2048 * 2048 / 10
GO
CREATE CLUSTERED INDEX pk ON [t] (c1)
GO
CREATE NONCLUSTERED INDEX i ON t (c2)
GO
이제이 데이터가 주어지면 다음 쿼리를 호출했습니다.
select *
from t
where
c2 < 1048576
or c2 is null
;
놀랍게도이 쿼리에 대해 생성 된 실행 계획은 이것 입니다. (외부 링크가 유감이므로 여기에 맞지 않습니다.)
누군가이 " Constant Scans "와 " Compute Scalars "가 어떻게 되는지 설명해 줄 수 있습니까 ? 무슨 일이야?
|--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1010], [Expr1011], [Expr1012]))
|--Merge Interval
| |--Sort(TOP 2, ORDER BY:([Expr1013] DESC, [Expr1014] ASC, [Expr1010] ASC, [Expr1015] DESC))
| |--Compute Scalar(DEFINE:([Expr1013]=((4)&[Expr1012]) = (4) AND NULL = [Expr1010], [Expr1014]=(4)&[Expr1012], [Expr1015]=(16)&[Expr1012]))
| |--Concatenation
| |--Compute Scalar(DEFINE:([Expr1005]=NULL, [Expr1006]=NULL, [Expr1004]=(60)))
| | |--Constant Scan
| |--Compute Scalar(DEFINE:([Expr1008]=NULL, [Expr1009]=(1048576), [Expr1007]=(10)))
| |--Constant Scan
|--Index Seek(OBJECT:([t].[i]), SEEK:([t].[c2] > [Expr1010] AND [t].[c2] < [Expr1011]) ORDERED FORWARD)