2013-04-26 3 views
1

저는 오라클에 처음 왔으며 고주파에서 사용할 두 가지 기능이 있습니다. 그리고 나는 그들 사이에 어느 쪽이 더 좋은지 궁금해.함수에서 count (*) 대신에 예외를 사용해야합니까?

이 하나

FUNCTION GET_MY_MONEY (myType IN NUMBER) RETURN NUMBER AS 
    var_amount NUMBER; 
    var_result NUMBER; 
BEGIN 
    var_result := 0; 
    var_amount := 0; 
    SELECT amount INTO var_amount FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to; 
    var_result := var_amount*1000; 
    RETURN var_result; 
EXCEPTION 
    WHEN OTHERS THEN 
     RETURN 0; 
END; 

하거나 하나의 성능을 위해 더 나은

FUNCTION GET_MY_MONEY (myType IN NUMBER) RETURN NUMBER AS 
    var_count NUMBER; 
    var_amount NUMBER; 
    var_result NUMBER; 
BEGIN 
    var_result := 0; 
    var_count := 0; 
    var_amount := 0; 
    SELECT count(*) INTO var_count FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to; 
    IF (var_count > 0) THEN 
     SELECT amount INTO var_amount FROM mytable WHERE type = myType AND sysdate >= date_from AND sysdate <= date_to; 
     var_result := var_amount*1000; 
     RETURN var_result; 
    ELSE RETURN 0; END IF; 
EXCEPTION 
    WHEN OTHERS THEN 
     RETURN 0; 
END; 

? 호출 될 때 더 빨리 복귀합니까?

미리 감사드립니다.

+1

1 접근이 더 좋다. 왜냐하면 count (*)는 무거운 연산이므로 –

+1

첫 번째 접근 방식을 사용합니다. 나는 당신이 사용 된 변수와 혼동하고 있다고 생각합니다. var_count는 처음에는 선언되지 않았고 두 번째에는 var_amount를 사용하지 않습니다. – Noel

+0

오타 (誤字)가 잘못되었습니다. 귀하의 지적에 감사드립니다. – PhatHV

답변

4

일반적으로 달라집니다. 얼마나 자주 함수를 호출하고 쿼리가 0 행을 반환하게하는 myType 값을 전달합니까?

호출의 99.9 %에서 쿼리가 정확히 1 행을 반환하면 두 번째 방법은 쿼리를 두 번 실행하여 두 번 실행합니다. 두 번째 호출은 관심있는 블록이 거의 캐시 될 것이므로 두 번째 호출이 첫 번째 함수보다 두 배 비싸지는 않지만, 두 번째 방법은 거의 확실히 느릴 것입니다.

반면에 호출의 상당 부분에 행을 반환하지 않는 myType 값이 포함되는 경우 두 번째 방법은 자주 쿼리를 두 번 실행할 필요가 없습니다. 그리고 첫 번째 접근법은 예외 처리에 소요되는 시간이 두 번째 쿼리보다 훨씬 비쌉니다.

대부분의 경우 0 행이 반환 될 확률에 따라보다 효율적인 해결책이 명확 해집니다. 대부분의 경우 함수는 호출자가 전달하는 값이 유효하다는 것을 확신 할 때만 호출되므로 첫 번째 방법이 더 효율적으로 끝납니다. 발견 된 행이 0이되도록하는 호출의 비율이 증가함에 따라 두 번째 접근 방식이 더 효율적입니다. 이 행은 테이블, 데이터, 하드웨어 및 Oracle 버전과 같은 여러 요소에 따라 달라집니다. 특정 코드에 대해 경계선이 10 % 또는 20 % 또는 90 %인지 여부를 결정하기 위해 벤치 마크 테스트를 실행해야합니다.또한

+0

제 경우에는 쿼리의 80 % 이상이 0 행을 반환합니다. 그러나 테이블을 스캐닝하는 데 2 ​​배의 비용이 소요되는 20 % 미만으로 남아 있습니다 (고려할만큼 충분히 큽니다). 왜 '예외 처리의 오버 헤드'가 더 비싸다는 것을 설명 할 수 있습니까? 나는 새롭고 오라클이 예외를 처리 할 때 장면 뒤에 무엇이 있는지 모릅니다. – PhatHV

+3

+1 분석을 위해, 비록 예외 오버 헤드가 함수 호출의 작은 부분에서 SQL 엔진에 대한 두 번째 호출과 비교할 때 0과 같다고 생각합니다. (확실하지는 않습니다. 이것은 단지 내기 일뿐입니다). 가장 좋은 방법은 nvl (sum (amount), 0)을 선택하는 것입니다. –

2

질문이 편집되었지만 행이 두 개 이상있는 경우 SELECT amount INTO var_amount ...이 실패합니다 (sum(amount)을 선택하고 싶을 수도 있음).

  • 가 두 번 테이블을 스캔하지 않는 훨씬 더 이해할 수 있습니다 : 때문에

    첫 번째 방법은 더 좋다.

  • 두 번째 에 var_amount가 표시되지만 사용하지 마십시오.
  • 개수 (*) 당신은 select nvl(sum(amount),0) as amount

그러나 날짜 변수 (date_fromdate_to)에 값을 할당하거나 매개 변수로 넣어야합니다 수, 쓸모가 없다. 그리고 식을 반환 할 수 있습니다. 즉, RETURN var_count*1000;

+0

예, 특히 예외를 트래핑 할 필요가없는 SUM()을 선택할 때 특히 그렇습니다. –

1

: 레코드의 숫자가 매우 높을 때

DECLARE 
    v_retVal NUMBER:= 0; 
    v_sal NUMBER:= 0; 
BEGIN 
    SELECT nvl(sum(sal),0) as sal INTO v_sal 
    FROM scott.emp 
    WHERE deptno = 40; -- no data for deptno = 40 

    -- No exception needed, function will always return 0 or value -- 
    v_retVal:= (CASE WHEN v_sal = 0 THEN 0 ELSE v_sal*1000 END); 

    dbms_output.put_line (v_retVal); 

    -- RETURN v_retVal; 
END; 
/
관련 문제