2017-04-02 15 views
2

PostgreSQL 9.6에서 발생하는 문제를 이해하고 (아마도 향상시킬 수 있습니다.) 궁금합니다. 이름은 단순화되었지만 나머지는 모두 psql 세션에서 가져 왔습니다.쿼리에서 COUNT 동작 이해 vs. EXPLAIN 대 함수

구체화 된보기, mv으로 시작합니다.

CREATE FUNCTION count_mv() RETURNS BIGINT AS $$ 
SELECT COUNT(*) FROM mv; 
$$ LANGUAGE SQL STABLE PARALLEL SAFE; 

CREATE FUNCTION mv_pks() RETURNS TABLE (table_pk INTEGER) AS $$ 
SELECT table_pk FROM mv; 
$$ LANGUAGE SQL STABLE PARALLEL SAFE; 

하자 시간 일부 쿼리 :

첫째, 나는 두 가지 간단한 기능을 만들 수 있습니다.

db=>\timing on

나는 매우 빠르게 구체화 된 뷰의 결과를 셀 수 있습니다.

db=> SELECT COUNT(*) FROM mv; 
    count 
--------- 
2567883 
(1 row) 

Time: 79.803 ms 

어떻게하는지 보자.

db=> EXPLAIN ANALYZE SELECT COUNT(*) FROM mv; 
                    QUERY PLAN 
----------------------------------------------------------------------------------------------------------------------------------------------- 
Finalize Aggregate (cost=41331.24..41331.25 rows=1 width=8) (actual time=765.681..765.681 rows=1 loops=1) 
    -> Gather (cost=41330.62..41331.23 rows=6 width=8) (actual time=765.557..765.670 rows=7 loops=1) 
     Workers Planned: 6 
     Workers Launched: 6 
     -> Partial Aggregate (cost=40330.62..40330.63 rows=1 width=8) (actual time=760.175..760.175 rows=1 loops=7) 
       -> Parallel Seq Scan on mv (cost=0.00..39261.09 rows=427809 width=0) (actual time=0.014..397.952 rows=366840 loops=7) 
Planning time: 0.326 ms 
Execution time: 769.934 ms 
(8 rows) 

좋습니다. 그래서 여러 명의 근로자를 이용하고 있습니다. 하지만 EXPLAIN ANALYZE을 사용할 때 쿼리가 왜 그렇게 느린가?

는 지금은 같은 기본 SQL을 가지고 있으며, STABLE를 선언 된 count_mv() 기능을 사용합니다.

db=> select count_mv(); 
    count_mv 
------------ 
    2567883 
(1 row) 

Time: 406.058 ms 

와우! 왜 이것이 Materialized View에서 동일한 SQL보다 느립니다? 그리고 훨씬 더 천천히! 평행 한 노동자를 이용하지 않습니까? 그렇지 않다면 왜 안됩니까? 다음 응답에 제안한

가 편집

을 시작 I는 auto_explain 모듈을로드하고, 함수 호출에 EXPLAIN는 로그 출력을 조사했다.

Query Text: 
    SELECT COUNT(*) FROM mv; 

    Finalize Aggregate (cost=41331.60..41331.61 rows=1 width=8) (actual time=1345.446..1345.446 rows=1 loops=1) 
     -> Gather (cost=41330.97..41331.58 rows=6 width=8) (actual time=1345.438..1345.440 rows=1 loops=1) 
      Workers Planned: 6 
      Workers Launched: 0 
      -> Partial Aggregate (cost=40330.97..40330.99 rows=1 width=8) (actual time=1345.435..1345.435 rows=1 loops=1) 
        -> Parallel Seq Scan on mv (cost=0.00..39261.38 rows=427838 width=0) (actual time=0.020..791.022 rows=2567883 loops=1) 

새로운 질문은 6 명의 직원이 계획되지만 아무도 시작되지 않는 이유입니다. 서버가 유휴 상태이고 구성이 동일하며 쿼리가 동일합니다.

최종 편집

좋습니다. 그래서 나는이 작업을 수행 할 경우 :

직접 EXPLAIN ANALYZE를 사용하지 않고 구체화 된 뷰에 행을 계산하지만, 당신이 여기 저를 신뢰해야합니다 동일한 성능
db=> SELECT COUNT(*) FROM mv_pks(); 
    count 
--------- 
2567883 
(1 row) 

Time: 72.687 ms 

:이 기능의 성능이의 상태에 따라 달라집니다 함수가 작성 될 때 구체화 된 뷰. 빠른 타이밍은 테이블이 비어있을 때 함수를 작성한 결과입니다. 테이블이 꽉 찼을 때 함수를 다시 만들면 함수를 실행하는 데 1000 밀리 초가 필요합니다!

내 질문을 요약하면 :

  1. 은 왜 함수 외부 쿼리보다 훨씬 느린 매개 변수를 고려하지 않는 STABLE SQL 함수 내부의 SQL 쿼리입니다.
  2. EXPLAIN ANALYZE을 사용할 때 SQL 쿼리의 속도가 느린 이유는 무엇입니까?
  3. 함수가 작성된시기에 따라 구체화 된보기의 행 수를 계산하는 것과 같거나 다른 방법보다 느릴 수있는 함수의 행을 계산할 때 왜 다른 결과가 나옵니 까?

미리 감사드립니다.

답변

1

1)에 대해서는 auto_explain을 사용하여 함수 내에서 쿼리에 대한 계획을 표시 할 수 있습니다. 그것은 병렬 계획을 사용합니까?

2)는 측정에 대한 오버 헤드이며 플랫폼에 따라 다르지만 높을 수 있습니다.

3) 두 경우 모두 SQL 계획을 비교하십시오. SQL 함수의 쿼리는 캐시되지 않기 때문에 왜 이렇게 행동해야하는지에 대한 설명이 없습니다. 디스크에서 읽는 것과 캐쉬에서 읽는 것의 효과를 확인하기 위해 테스트를 여러 번 반복 했습니까?

+0

응답 해 주셔서 감사합니다. 1) 굉장한 모듈. 그것은 많은 것들을 위해 매우 도움이 될 것입니다. 새로운 Explain 출력에서 ​​병렬성이 부족한 이유에 대한 의견은 있습니까? 2) 알았어요. 말이된다; 거의 10 배 놀랐습니다. 3) 예. 여러 번 시험을 보았습니다. 나는 심지어 같은 SQL을 사용하는 두 가지 기능을 가지고 있었지만, 서로 다른 생성 시간을 사용하여 하나씩 실행하고 다른 결과를 얻을 수있었습니다. 기묘한! – rg6

+0

포인트 3)은 여전히 ​​나에게 불분명하다. 나는 실험했지만 재현 할 수 없었다. 재현 가능한 테스트 케이스를 찾을 수 있습니까? –

+0

1)에 대한 편집을 추가했습니다. 수상 내역 : 함수 내의 동일한 SQL이 병렬 처리 계획을 사용하지 않는 이유에 대해 언급 할 수 있습니다. 아니면 EXPLAIN 출력을 잘못 해석합니까? 3) 테스트 케이스에서 어떤 행동을보고 있습니까? 아니요, 이것을 신뢰할 수있게 재현 할 수는 없으며 그 점은 만족스럽지 않습니다. 어제는 빠른 성능으로 기능을 만들 수 없었습니다. 오늘은 느린 성능으로 하나를 만들 수 없습니다. 그러나 성능이 다른 기존 함수는 '\ df +'와 동일한 코드를 보여줍니다. – rg6