SQL에서 발견 된 큰 성능 차이 (1 시간 ~ 1 분). 이유를 설명해 주시겠습니까?

StackOverflow https://stackoverflow.com/questions/1819513

문제

다음 쿼리는 1 백만 레코드의 표준 기계에서 각각 70 분 1 분이 걸립니다. 가능한 이유는 무엇입니까?

쿼리 [01:10:00

SELECT * 
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
    CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        ELSE sys.fn_cdc_increment_lsn(0x00) END
    , sys.fn_cdc_get_max_lsn()
    , 'all with mask') 
WHERE __$operation <> 1

수정 된 쿼리 [00:01:10

DECLARE @MinLSN binary(10)
DECLARE @MaxLSN binary(10)
SELECT @MaxLSN= sys.fn_cdc_get_max_lsn()
SELECT @MinLSN=CASE WHEN sys.fn_cdc_increment_lsn(0x00)<sys.fn_cdc_get_min_lsn('dbo_PartitionTest')     
        THEN sys.fn_cdc_get_min_lsn('dbo_PartitionTest')        
        ELSE sys.fn_cdc_increment_lsn(0x00) END

SELECT * 
FROM cdc.fn_cdc_get_net_changes_dbo_PartitionTest(
        @MinLSN, @MaxLSN, 'all with mask') WHERE __$operation <> 1

수정

각 행에 대해 매개 변수가 평가되는지 확인하기 위해 비슷한 기능으로 시나리오를 재현하려고했습니다.

CREATE FUNCTION Fn_Test(@a decimal)RETURNS TABLE
AS
RETURN
(
    SELECT @a Parameter, Getdate() Dt, PartitionTest.*
    FROM PartitionTest
);

SELECT * FROM Fn_Test(RAND(DATEPART(s,GETDATE())))

그러나 38 초 만에 AA 백만 레코드에 대한 열 '매개 변수'열에 대해 동일한 값을 얻고 있습니다.

도움이 되었습니까?

해결책

결정 론적 스칼라 함수조차도 행 당 한 번 이상 평가됩니다. 동일한 결정 론적 스칼라 함수가 동일한 매개 변수로 동일한 "행"에서 여러 번 발생하면, 예를 들어 CASE WHEN fn_X(a, b, c) > 0 THEN fn_X(a, b, c) ELSE 0 END 또는 그런 것.

나는 당신의 랜드 문제가 당신이 계속 재개하기 때문이라고 생각합니다.

동일한 종자 값을 가진 Rand ()의 반복 호출은 동일한 결과를 반환합니다.

하나의 연결의 경우, rand ()가 지정된 종자 값으로 호출되면 rand ()의 모든 후속 호출은 시드 랜드 () 호출을 기반으로 결과를 생성합니다. 예를 들어, 다음 쿼리는 항상 동일한 숫자 순서를 반환합니다.

나는 당신이 지적한대로 스칼라 함수 결과를 캐싱했습니다. 심지어 스칼라 기능 결과의 테이블을 미리 계산하고 그들과 결합하는 것까지도 진행했습니다. 스칼라 기능을 수행하기 위해 결국 무언가를해야합니다. 맞지 않습니다. 가장 좋은 옵션은 CLR입니다. 불행히도, 나는 현재 환경에서 그것들을 사용할 수 없습니다.

다른 팁

첫 번째 쿼리에서 fn_cdc_increment_lsn 그리고 fn_cdc_get_min_lsn 모든 행에 대해 실행됩니다. 두 번째 예에서는 한 번만.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top