Q&A

[Q&A] PostgreSQL 9.6 성능 이야기

PostgreSQL 9.6 성능 이야기 관련 Q&A 페이지입니다.  아래 페이지에 질문을 등록해주시면 최대한 빠르게 답변드리겠습니다. 감사합니다.

Q&A #3

답변 (김시연): 2017-04-12

네. 맞습니다. JPPD 실패 시의 문제점을 부각(?)시키기 위해서 Merge Join을 disable 했는데요. 그 부분이 빠져있습니다. 이 부분은 책에도 추가를 해야겠습니다. 감사합니다 🙂

참고로, Merge Join으로 수행될 경우에는 입력 값에 따라서 성능 편차가 있습니다. 예제의 경우는 빠르게 나오지만 “a.c2=999999″와 같이 뒷 부분의 값을 입력하면 느립니다.

질문: eqon19 : 2017-04-12

전자책 228페이지 아래 JPPD실패하는 경우의 예제 테스트해보니까

QUERY PLAN
————————————————————————–
Merge Join (actual rows=1 loops=1)
 Merge Cond: (t3.c1 = a.c1)
 -> GroupAggregate (actual rows=12 loops=1)
 Group Key: t3.c1
 -> Index Scan using t3_c1_indx on t3 (actual rows=25 loops=1)
 -> Materialize (actual rows=1 loops=1)
 -> Sort (actual rows=1 loops=1)
 Sort Key: a.c1
 Sort Method: quicksort Memory: 25kB
 -> Index Scan using t2_uk on t2 a (actual rows=1 loops=1)
 Index Cond: (c2 = 10)
 Planning time: 0.981 ms
 Execution time: 0.327 ms

위처럼 나오는데

set enable_mergejoin=off;
이렇게 먼저 해줘야 책과 같은 실행계획이 나오네요. 확인 부탁드려요.

 QUERY PLAN
—————————————————————————–
Hash Join (actual rows=1 loops=1)
 Hash Cond: (t3.c1 = a.c1)
 -> GroupAggregate (actual rows=2000000 loops=1)
 Group Key: t3.c1
 -> Index Scan using t3_c1_indx on t3 (actual rows=4000000 loops=1)
 -> Hash (actual rows=1 loops=1)
 Buckets: 1024 Batches: 1 Memory Usage: 9kB
 -> Index Scan using t2_uk on t2 a (actual rows=1 loops=1)
 Index Cond: (c2 = 10)
 Planning time: 0.324 ms
 Execution time: 1654.565 ms

Q&A #2

답변 (김시연): 2017-04-12

제 환경에서도 몇 차례 더 테스트를 수행해봤습니다. 제 환경에서는 책과 동일하게 In-Memory 방식의 속도가 약간 느립니다. eqon19님과는 다른 결과가 나오는건데요.

먼저, 저 처럼 In-Memory 방식이 느린 경우는 In-Memory 방식에서의 해시 충돌에 대한 부하가 Multi-Batch 방식에서의 Temp IO 부하보다 더 클 때입니다.
만일 반대의 경우라면 In-Memory 방식이 더 빠르겠죠.

그런데 eqon19님의 환경은 SSD이고, Explain 결과를 보면 제 환경보다 IO 속도가 더 빠릅니다. 즉, Temp IO의 부하가 더 적습니다. 따라서 Multi-Batch 시의
Temp IO 부하가 더 적으므로 Multi-Batch의 속도가 더 빠를 것 같지만, 결과는 오히려 In-Memory가 빠릅니다.

아마 이런 결과가 나온 이유는, 해시 테이블 검색 속도, 즉 CPU 속도가 제 환경보다 빨라서 인 것으로 보입니다.  참고로 제 PC 환경은 Intel-Core i7-6500U 2.50GHz 입니다.

질문: eqon19 : 2017-04-11

전자책 198페이지 질문 좀 드릴게요. 아래와 같이 테스트해봤는데 책과는 다르게 in-memory방식이 더 빠른건 왜일까요.. 테스트환경은 SSD를 사용하고 있는데 관계가 있을까요

postgres=# set work_mem=’1MB’;
SET
 postgres=#
 postgres=# explain (costs false, analyze, buffers)
 postgres-# select *
 postgres-# from t1 a, t2 b
 postgres-# where a.c1=b.c1;
 QUERY PLAN
———————————————————————————-
Hash Join (actual time=214.777..1924.983 rows=4000000 loops=1)
 Hash Cond: (b.c1 = a.c1)
 Buffers: shared hit=16300 read=10728 written=14, temp read=21217 written=21091
 -> Seq Scan on t2 b (actual time=0.022..312.475 rows=4000000 loops=1)
 Buffers: shared hit=14793 read=6829 written=1
 -> Hash (actual time=214.309..214.309 rows=1000000 loops=1)
 Buckets: 32768 Batches: 64 Memory Usage: 976kB
 Buffers: shared hit=1507 read=3899 written=13, temp written=4176
 -> Seq Scan on t1 a (actual time=0.006..80.531 rows=1000000 loops=1)
 Buffers: shared hit=1507 read=3899 written=13
 Planning time: 0.107 ms
 Execution time: 2082.692 ms
 (12 rows)
postgres=#
 postgres=# set work_mem=’100MB’;
SET
 postgres=#
 postgres=# explain (costs false, analyze, buffers)
 postgres-# select *
 postgres-# from t1 a, t2 b
 postgres-# where a.c1=b.c1;
 QUERY PLAN
——————————————————————————-
Hash Join (actual time=278.591..1791.172 rows=4000000 loops=1)
 Hash Cond: (b.c1 = a.c1)
 Buffers: shared hit=16240 read=10788
 -> Seq Scan on t2 b (actual time=1.078..280.867 rows=4000000 loops=1)
 Buffers: shared hit=14765 read=6857
 -> Hash (actual time=274.582..274.582 rows=1000000 loops=1)
 Buckets: 1048576 Batches: 1 Memory Usage: 54091kB
 Buffers: shared hit=1475 read=3931
 -> Seq Scan on t1 a (actual time=0.015..98.582 rows=1000000 loops=1)
 Buffers: shared hit=1475 read=3931
 Planning time: 0.140 ms
 Execution time: 1941.265 ms

Q&A #1 

답변 (김시연) : 2017-04-04


아래의 예제를 그대로 수행하면 말씀하신 것처럼 Merge Join으로 수행되는 것이 맞습니다. 현재 해당 쿼리를 가장 빠르게 수행하는 방법이 Merge Join이기 때문입니다. 그런데 설명을 위해서 제가 다른 조인 방법을 모두 off 해두었는데, 이 부분이 책에 빠져있습니다. ㅠㅠ

즉, 수행 전에

set enable_mergejoin=off;
set enable_hashjoin=off;

를 수행하고 테스트를 했는데, 이 부분이 책에 빠져있습니다. 4월2주차 출간본에는 해당 부분을 추가하도록 하겠습니다. 감사합니다. 🙂

질문:  eqon19 says:| 4월 4, 2017 (2:37 오후) 편집

질문 좀 드릴게요. 책 124페이지 맨위에 Nested Loop실행계획 부분이요. 똑같이 따라 했는데 아래처럼 Merge join으로 풀리는 이유가 뭘까요. 딱히 파라미터 바꾼게 없는것 같은데… 어떤 파라미터가 영향을 미쳤을까요.. 굳이 따지자면 테스트환경은 디스크 SSD 사용하고 있습니다만…

postgres=# explain
postgres-# select *
postgres-# from t1 a, t2 b
postgres-# where a.c1=b.c1;

QUERY PLAN
———————————————————————————–
Merge Join (cost=2.54..4.53 rows=10 width=2016)
Merge Cond: (b.c1 = a.c1)
-> Index Scan using t2_idx01 on t2 b (cost=0.28..181.28 rows=1000 width=1008)
-> Sort (cost=2.27..2.29 rows=10 width=1008)
Sort Key: a.c1
-> Seq Scan on t1 a (cost=0.00..2.10 rows=10 width=1008)