2015-01-30 6 views
1

이 질문은 후속 조치로 제공되며 결과는 SQL function very slow compared to query without function wrapper입니다. 나는이 질문이 특정 문제에 대한 해결책을 요구하고 있었기 때문에 이것을 중복으로 생각하지 않는다는 것을 알아야한다. 나는 일반적으로 여기에있는 행동에 대한 더 많은 정보를 요구하고 그것을 재현 할 수있는 방법을 시연한다. (차이점을 증명하기 위해, 우리는 행동을 논의한 곳에서 받아 들여진 대답에 대해 상당히 긴 코멘트 스레드를 볼 수 있습니다. 특히 길이가 주어지면 주제를 벗어났다는 느낌이 들었습니다.)변동성이 다른 기능에 대해 계획자가 다른 결과를 얻는 이유는 무엇입니까?

나는 기능이 있습니다. 나는 거대한를 제거했습니다 psql의에서이 결과를 (얻을

EXPLAIN ANALYZE SELECT * FROM test(10); 

"쿼리 계획"헤더 :

CREATE OR REPLACE FUNCTION test(INT) 
    RETURNS TABLE(num INT, letter TEXT) 
    VOLATILE 
    LANGUAGE SQL 
    AS $$ 
    SELECT * 
    FROM (VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')) x 
    LIMIT $1 
    $$; 

나는이 EXPLAIN을 실행하면 다음과 같습니다 관심의 동작을 나타내는 샘플 하나입니다) :

Function Scan on test (cost=0.25..10.25 rows=1000 width=36) (actual time=0.125..0.136 rows=5 loops=1) 
Total runtime: 0.179 ms 
(2 rows) 

행 추정에 유의하십시오. 그것은 1000 행을 견적.

하지만, 내가 STABLE 또는 IMMUTABLE의 기능을 변경하는 경우 :

CREATE OR REPLACE FUNCTION test(INT) 
    RETURNS TABLE(num INT, letter TEXT) 
    STABLE 
    LANGUAGE SQL 
    AS $$ 
    SELECT * 
    FROM (VALUES (1,'a'),(2,'b'),(3,'c'),(4,'d'),(5,'e')) x 
    LIMIT $1 
    $$; 

그런 다음 같은 EXPLAIN 나에게 다른 계획을 제공합니다

Limit (cost=0.00..0.06 rows=5 width=36) (actual time=0.010..0.050 rows=5 loops=1) 
    -> Values Scan on "*VALUES*" (cost=0.00..0.06 rows=5 width=36) (actual time=0.005..0.018 rows=5 loops=1) 
Total runtime: 0.087 ms 
(3 rows) 

지금은 정확히 5 개 행을 추정, 그리고 그것을 보여줍니다 함수 내에 포함 된 질의에 대한 계획. 비용은 한 단계 높은 수준입니다. 런타임도 다운되었습니다. 쿼리가 너무 짧아서별로 중요하지 않을 수도 있습니다.

훨씬 많은 데이터를 처리하고 성능상의 차이가 큰 링크 질문에 비추어 볼 때 플래너는 실제로 다른 무언가를하고있는 것 같습니다. 기능이 VOLATILE 또는 STABLE/IMMUTABLE인지 여부.

여기서 계획자는 무엇을하고 있으며, 어떤 문서를 읽을 수 있습니까?

이러한 테스트는 PG 9.3에서 실행되었습니다.

+1

*** 인라이닝 ***이 설명의 열쇠일지도 모릅니다. 'STABLE' 변형은 "인라인"될 수 있습니다 (함수에서 풀지 않은 쿼리 내에서 SQL 코드가 효과적으로 실행됩니다.) 더 이상 실행하지 않아도됩니다 –

답변

2

CREATE FUNCTION에 설명 된 기본 값을 1000 행

1000 추정 행을 계산합니다 :

execution_cost

에 대한 예상 실행 비용을 제공 양수 함수를 cpu_operator_cost의 단위로 사용합니다. 함수가 집합을 반환하면 반환 된 행당 비용입니다. 비용이 지정되지 않은 경우 C 언어 및 내부 기능의 경우 단위는 이고 다른 모든 언어의 기능은 단위는 입니다. 값이 클수록 플래너 은 필요한 것보다 더 자주 기능 평가를 피하려고합니다.

result_rows

플래너 함수가 반환 할 것으로 예상한다 예상 행 수를 나타내는 양수. 함수가 집합을 반환하도록 선언 된 경우에만 이 허용됩니다. 기본 가정 은 1000 행입니다.

함수가 휘발성으로 선언되면 인라인되지 않기 때문에 result_rows의 기본값이 적용됩니다.

반면에 두 번째 테스트에서와 같이 쿼리에서 인라인 될 때 ​​행의 수는 함수의 본문이 쿼리로 옮겨지고 함수 선언에 ' 존재하지 않습니다. 이것은 VALUES 절이 직접 평가 될 수 있기 때문에 두 번째 테스트에서 정확한 추정을 유도합니다.

바로 여기에서하고있는 계획이며, 어디에서 나는 그것에 몇 가지 문서를 읽을 수 있습니까?

일반적으로 플래너의 최적화 전략은 주 문서에서 설명하지 않습니다. 그것들은 메일 링리스트에서 논의되고 소스 코드 주석에 언급되어 있습니다. 다행스럽게도 예외적으로 명확하고 잘 작성되는 경향이 있습니다 (평균 소스 코드와 비교). 함수 인라이닝의 경우, inline_set_returning_functionsinline_set_returning_function의 코멘트는이 특별한 최적화를 이끌어내는 대부분의 규칙을 나타냅니다. (경고 : 위의 링크는 언제든지 변경되거나 표류 할 수있는 현재 마스터 브랜치에 있습니다.)

+0

인라인 함수에 대한 문서를 가리킬 수 있습니까? 무엇이든 사냥 할 수있게되었습니다. – jpmc26

+0

@ jpmc26 : 정말로 그렇지 않습니다. 가장 최근의 편집을 봅니다. –