2010-01-15 3 views
3

아래 쿼리에서 성능 향상을 위해 case 문을 UDF로 옮기는 것이 좋습니다. 그렇다면 왜?select가 계산을 수행 할 때 SQL 성능 향상

SELECT id, 
     name, 
     case 
     when v1 = 'Y' then 'something' 
     when v2 = 'K' then 'something else' 
     when v3 is null then 'dont know' 
     else 'default' 
     end 
from table 

답변

2

아니요 나는 그대로있는 것입니다. UDF를 사용하면 (일반적으로) 일부는 wierd side effects and limitations 일 수 있으며이 조회는 단순히 UDF를 g 용하는 것이 정당하지 않습니다. UDF 성능은이 직접 쿼리에서 얻은 것보다 낫지 않아야합니다. http://www.bennadel.com/blog/964-SQL-User-Defined-Functions-Are-Slower-Than-Inline-Logic.htm

+0

좋은 물건. 정보를 주셔서 감사합니다 –

+0

어떤 방식 으로든 UDF에서 데이터를 변경할 수 없기 때문에 UDF의 유일한 이상한 부작용은 성능 저하 일 수 있습니다. 즉, UDF는 선택 W 계산 만 수행 할 수 있으며 삽입 W 갱신은 수행 할 수 없습니다. –

+0

UDF의 다른 wierd 제한 사항을 설명하는 링크를 추가했습니다 (예 : GETDATE와 같은 비 결정적 내장 함수를 사용할 수 없음) –

1

에는, UDF는 일반적으로 쿼리에서 다음 case 문을 최악을 수행 할 것입니다 :

여기에 관련 블로그 항목입니다. 그러나 대부분의 SQL을 사용하면 두 가지를 모두 시도하고 결과를 비교하는 것이 가장 좋습니다.

0

별도의 UDF로 이동할 경우 효과가 없을 것입니다. SQL Server는 성능을 위해 이러한 유형의 작업을 최적화하므로 UDF는 어쨌든 "인라인"될 것입니다.

+0

재미있는 점은 어떻게 든 코드를 인라인 할 것입니까? 그 점에 대한 언급이 있습니까? – AnthonyWJones

0

(유감스럽게도 내가 읽은 곳을 기억하지 못합니다.) "간단한"구문 형식의 case 문을 사용할 때 옵티마이 저가 더 나은 실행 계획을 얻을 수 있습니다. 궁극적으로 짧은 형식은 구문 론적 설탕 일 뿐이지 만, 복잡한 비교가 포함되지 않은 상태에서 모든 비교가 간단한 평등 기반이라는 힌트를 옵티마이 저가 제공합니다.

귀하가 3 개의 다른 열, v1, v2 및 v3을 사용 중이므로 주어진 사례 설명을 전환 할 수 없습니다. 모든 동일한 열을 사용하고 경우에, V1은,이 수정 번 더 수행 할 수에서 말 :

SELECT 
    id, 
    name, 
    case Coalesce(v1, 'dont know') 
     when 'Y' then 'something' 
     when 'K' then 'something else' 
     when 'dont know' then 'dont know' 
     else 'default' 
    end 
from table 

좋아, 어쩌면이 때문에 널 (null) 처리에 필요한 conniptions로 적합하지 않습니다. 나는 일반적인 최적화 힌트를 찾고 있기 때문에 어떤 경우에는 가능한 최적화를 지적하고자했다.

UDF가 성능이 떨어지는 것에 대해서는 전적으로 동의합니다. 인라인은 거의 보편적으로 성능 향상을 제공합니다. 옵티마이 저가 비밀리에 그것을 인라인하지 않는 한 전화를 걸고 콜에서 돌아 오는 데 필요한 모든 작업을 피할 수 있기 때문입니다.

이 특정한 경우에 또 다른 아이디어는 당신이 리터럴 값의 전체 파생 테이블과 조인을 사용하는 것이 좋습니다 것입니다

: 방식 내가 할 선택했기 때문에 다시

SELECT 
    id, 
    name, 
    coalesce(x.result, 'dont know') 
from 
    table t 
    left join (
     select 'Y', 'something' 
     union all select 'K', 'something else' 
     union all select '%', 'default' 
    ) x (value, result) on t.v1 like x.value 

은이 완벽하지 않을 수 있습니다 LIKE로 null 처리. 그러나이 기술을 적절하게 시연합니다.

추가 포인트 :

  • 테스트는 어떤 상황에서 최고의 성능을 제공 무엇인지 찾기 위해 항상이다. 100,000 또는 100 만 행으로 가득 찬 테이블을 채우고 CPU, 읽기, 쓰기 및 지속 시간을 캡처하기 위해 실행중인 프로파일 러로 몇 가지 테스트를 수행하십시오. 더 낮은 기간에 더 낮은 cpu/읽기를 선호하십시오.

  • 실행 계획은 종종 좋은 지침이지만 UDF의 내부 비용을 완전히 무시하고 cpu/read tradeoffs를 제대로 노출하지 않기 때문에 실행 계획 비용을 절대 신뢰하지 마십시오.

  • 소수의 읽기조차도 피하려면 대개 작은 CPU를 사용하는 것이 좋습니다.위에 사용 된 파생 테이블의 실행 계획에 나타나는 "상시 스캔"은 항상 소액의 비용이 소요됩니다. 이 비용은 디스크 액세스와 관련된 거의 모든 읽기보다 훨씬 적습니다.