2010-03-22 6 views
3

뷰를 가지고 있는데 (실제로는 테이블 값을 갖는 함수이지만 관찰 된 동작은 둘 다 동일합니다) 내부 조인과 왼쪽 외부 조인은 다른 여러 테이블을 조인합니다. 내가SQL Where Clause Again View

SELECT * 
FROM [v_MyView] 
WHERE [Name] like '%Doe, John%' 

유사한 where 절에이 뷰를 쿼리 할 때 ... 쿼리가 매우 느리게,하지만 내가 할 경우 훨씬 빠릅니다 ...

SELECT * 
FROM [v_MyView] 
WHERE [ID] in 
(
    SELECT [ID] 
    FROM [v_MyView] 
    WHERE [Name] like '%Doe, John%' 
) 

를 다음과 같습니다. 첫 번째 쿼리는 두 번째 쿼리가 5 초 이내에 반환되지 않을 경우 반환하는 데 적어도 2 분이 소요됩니다.

개선 방법에 대한 의견이 있으십니까? 뷰를 사용하지 않고 전체 명령을 하나의 SQL 문으로 실행하면 매우 빠릅니다. 이 결과는 뷰가 OUTER JOINS, GROUP BYS 또는 TOP ##을 가진 경우 뷰가 테이블로 동작해야하므로 뷰가 실행 된 후 where 절이 vs보다 먼저 해석 된 경우 결과가 다르다. 내 질문은 왜 SQL은 내 첫 번째 쿼리를 두 번째 쿼리만큼 효율적으로 최적화하지 않는 것입니까?

편집

그래서, 예를 세우는 작업을하고 백본으로 일반적으로 사용 가능한 AdventureWorks 데이터베이스를 사용하려고했다. 내 상황을 복제하는 동안 (누군가 다른 사람이 개발 한 느린 프로세스를 실제로 디버깅하는 것은 모두가 아닌가?) 동일한 결과를 얻을 수 없었습니다. 디버깅을하는 쿼리를 자세히 살펴보면이 문제가 사용자 정의 스칼라 가치 함수의 광범위한 사용과 관련 될 수 있음을 알게되었습니다. 전달하는 값에 따라 lastname, firstname 또는 firstname lastname 등의 형식을 사용하는 "GetDisplayName"함수가 많이 사용됩니다.이 함수를 생략하고 기본 쿼리/TVF/view에서 문자열 형식을 지정하거나 성능이 뛰어납니다. 실행 계획을 살펴보면,이 문제를 내가 초기에 무시한 이유 인 것처럼 보일 수있는 단서를주지 못했습니다.

+2

이상한 ... 두 쿼리 계획은 어떻게 생겼습니까? –

+0

TVF가 인라인이라고 생각합니까? 어떤 경우이든 그 정의를 게시 할 수 있습니까? –

답변

1

스칼라 UDF는 매우 가능성이 문제입니다. 그들이 당신의 질의로 들어가 자마자 당신은 RBAR 실행 계획을 가지고 있습니다. SELECT에 있지만 WHERE 절이나 JOIN 절에서 사용되는 경우에는 용인 될 수 있습니다. ...

매우 유용 할 수 있지만 큰 SELECT에서 성능 저하 요인이되기 때문에 유감입니다. 가능한 경우 UDF를 테이블 값으로 재 작성하거나 UDF를 피하기 위해 u 리를 재 작성하려고 시도하는 것이 좋습니다.

+0

이것은 TVF 내의 선택의 일부입니다. 따라서 TVF는 n 개의 테이블을 선택하고 UDF를 사용하여 결과의 ​​형식을 지정합니다.내가 TVF에 맞춰 선택했다면 나쁘지 않다고 말하는거야? –

+0

나는 너를 따라 오는지 잘 모르겠다. 기본 점은 스. 라 함수가 세트 기반 솔루션에 최적화 될 수 없기 때.에 서 v가 각 행을 개별적으로 실행하도록 강요한다는 것입니다. 따라서 사용하는 경우 행 수의 최소 수에 도달해야합니다 WHERE 및 JOIN의 제한 사항 이후에 수행됩니다. SELECT * FROM Table WHERE UdfResult (Param) = 1을 쓰는 일은 피해야합니다! 가능하다면 GetDisplayName을 가장 마지막 바깥 쪽 셀렉트로 옮기거나 세트 기반 작업으로 다시 작성하십시오. 실제로 무엇을하고 있습니까? – eftpotrm

+0

뷰를 선택하면이 udf가 호출됩니다. 그래서 뷰에 대한 where 절이 udf에 의해 생성 된 열에 대해 반대되는 경우 성능이 저하됩니다. udf 로직을 구현하기 위해 뷰를 변경하면 인라인 성능이 크게 향상됩니다. –

1

비록 제가 SQL 전문가는 아니지만 대부분의 경우 두 번째 쿼리에서 더 빨리 만드는 두 번째 쿼리 열과 두 번째로 ID 열이 일부 키로 표시되어 인덱싱된다는 사실 때문일 가능성이 큽니다. 이것이 두 번째 방법이 더 빠른 이유 일 수 있습니다.

첫 번째 쿼리 :

SELECT * FROM [v_MyView] WHERE [Name] like '%Doe, John%' 

두 번째 쿼리

SELECT * FROM [v_MyView] WHERE [ID] in 
(SELECT [ID] FROM [v_MyView] WHERE [Name] like '%Doe, John%') 
+0

당신이 옳았는데 그것이 내가 생각한 것입니다. 보기의 주 테이블에있는 ID를 선택한 다음 외부 조인의 외부 조인에있는 LastUpdatedDateTime을 선택하면 훨씬 느려집니다. 내 질문은, 그것을 최적화하기 위해 SQL에서 할 수있는 것이 있습니까? 내 쿼리가 필요한 것을 반환합니다. SQL이 내부적으로이 최적화를 수행하지 않았습니까? –