SQL Server는 모든 행에 대해 함수를 한 번 평가합니까?


9

다음과 같은 쿼리가 있습니다.

SELECT col1
FROM   MyTable
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 
       BETWEEN col2 
       AND     col3
;

다음과 유사한 실행 계획에 대한 툴팁이 제공됩니다.

실행 툴팁

dateadd탐색 술어 의 일부가 쿼리의 모든 행에 대해 실행됩니까? 아니면 SQL Server가 전체 쿼리에 대해 값을 한 번 계산합니까?

답변:


13

런타임 상수 로 알려진 특정 함수는 상수 접기 라는 프로세스를 거칩니다 . 상수를 '폴딩'하면 쿼리 실행 초기에 표현식이 평가되고 결과는 캐시되고 필요한 경우 캐시 된 결과가 대신 캐시됩니다. 쿼리의 표현은 DATEADD(dd, 0, DATEDIFF(dd, 0, getdate()))런타임 상수이므로 afaik은 쿼리 당 한 번만 접 히고 평가됩니다.

사소한 RAND()일로 : 접을 수 없을 것으로 예상 되는 기능은 실제로 접을 수 있으므로 예기치 않은 동작이 발생합니다. 그러나 다른 예를 들어 NEWID()접을 수 없으며 행마다 평가를 수행합니다.


2
@StuartBlackler- 다음 은 SQL Server가 다음과 같은 기능을 수행하는 방법을 보여줍니다GETDATE() .
Nick Chammas

2

실행 계획은 훌륭하지만 때로는 진실을 말하지 않습니다. 여기 성능 테스트를 기반으로 한 증명이 있습니다.

(그리고 결론-모든 행에 대해 표현식이 평가되는 것은 아닙니다)


;with t(i) as (select 0 union all select i+1 from t where i < 9)
select getdate()-1 as col1,getdate() as col2,getdate() as col3 
into #t 
from t t0,t t1,t t2,t t3,t t4,t t5,t t6,t t7

(100000000 개의 행이 영향을 받음)

이것은 OP 쿼리이며 실행하는 데 약 12 ​​초가 걸립니다.

SELECT col1
FROM   #t
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 
       BETWEEN col2 
       AND     col3
;

실행 전에 매개 변수에 날짜를 저장하는이 쿼리는 12 초 정도의 시간이 걸립니다.

declare @dt datetime = DATEADD(dd, 0, DATEDIFF(dd, 0, GETDATE())) 

SELECT col1
FROM   #t
WHERE  
      @dt
       BETWEEN col2 
       AND     col3
;

그리고 결과를 확인하기 위해
-col1에서 계산을 수행하므로 모든 행의 표현식을 다시 계산 해야하는이 쿼리는 실행하는 데 약 30 초가 걸립니다.

SELECT col1
FROM   #t
WHERE  
    DATEADD(dd, 0, DATEDIFF(dd, 0, col1)) 
       BETWEEN col2 
       AND     col3
;

동일한 쿼리에 대해 모든 쿼리가 반복적으로 실행되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.