19.7. 쿼리 플랜

19.7.1. 플래너 방법 환경 설정
19.7.2. 플래너 비용 상수
19.7.3. 유전 쿼리 최적화
19.7.4. 실행 계획기 관련 기타 옵션들

19.7.1. 플래너 방법 환경 설정

이 환경 설정 매개 변수는 쿼리 옵티마이저에 의해 선택된 쿼리 플랜에 영향을 주는 대략적인 방법을 제공한다. 특정 쿼리에 대한 옵티마이저에 의해 선택된 기본 플랜이 최적이 아닌 경우 임시 솔루션이 이 환경 설정 매개 변수 중 하나를 사용하여 옵티마이저가 다른 플랜을 선택하게 강제할 수 있다. 옵티마이저가 선택한 플랜의 수준을 개선하는 더 나은 방법은 플래너 비용 상수를 조절하고(19.7.2절 참조), ANALYZE를 수동으로 실행하고, default_statistics_target 환경 설정 매개 변수 늘리고, ALTER TABLE SET STATISTICS를 사용하여 특정 칼럼에 대해 수집된 통계량을 늘리는 것이다.

enable_bitmapscan (boolean)

쿼리 플래너의 bitmap-scan plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

enable_gathermerge (boolean)

Enables or disables the query planner's use of gather merge plan types. The default is on.

enable_hashagg (boolean)

쿼리 플래너의 hashed aggregation plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

enable_hashjoin (boolean)

쿼리 플래너의 hash-join plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

enable_incremental_sort (boolean)

Enables or disables the query planner's use of incremental sort steps. The default is on.

enable_indexscan (boolean)

쿼리 플래너의 index-scan plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

enable_indexonlyscan (boolean)

쿼리 플래너의 index-only-scan plan types 사용을 활성화 또는 비활성화한다 (11.9절 참조). 기본값은 on이다.

enable_material (boolean)

쿼리 플래너의 materialization의 사용을 활성화 또는 비활성화한다. materialization을 완전히 억제하는 것은 어렵지만 이 변수를 해제하면 정확도가 요구되는 경우 외에는 플래너의 materialize 노드 삽입이 방지된다. 기본값은 on이다.

enable_mergejoin (boolean)

쿼리 플래너의 merge-join plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

enable_nestloop (boolean)

쿼리 플래너의 nested-loop join plans 사용을 활성화 또는 비활성화한다. nested-loop joins를 완전히 억제하는 것은 어렵지만 이 변수를 해제하면 사용 가능한 다른 방법이 있는 경우 플래너가 하나를 사용하는 것이 방지된다. 기본값은 on이다.

enable_parallel_append (boolean)

Enables or disables the query planner's use of parallel-aware append plan types. The default is on.

enable_parallel_hash (boolean)

Enables or disables the query planner's use of hash-join plan types with parallel hash. Has no effect if hash-join plans are not also enabled. The default is on.

enable_partition_pruning (boolean)

Enables or disables the query planner's ability to eliminate a partitioned table's partitions from query plans. This also controls the planner's ability to generate query plans which allow the query executor to remove (ignore) partitions during query execution. The default is on. See 5.11.4절 for details.

enable_partitionwise_join (boolean)

쿼리 실행 계획기가 파티션와이즈 조인을 사용할지를 지정한다. 파티션와이즈 조인이란 각 짝이 맞는 하위 파티션 테이블들 끼리 조인 작업을 하는 것을 말한다. 현재 버전에서의 파티션와이즈 조인은 조인 조건에 모든 파티션 키를 사용하는 경우에만 작동한다. 각 조인 칼럼의 자료형도 같아야하며, 하위 파티션 집합도 각각 짝이 맞아야한다. 파티션와이즈 조인 계획 짜는 작업은 보다 많은 CPU 자원과 메모리를 사용하기 때문에, 기본값은 off다.

enable_partitionwise_aggregate (boolean)

Enables or disables the query planner's use of partitionwise grouping or aggregation, which allows grouping or aggregation on a partitioned tables performed separately for each partition. If the GROUP BY clause does not include the partition keys, only partial aggregation can be performed on a per-partition basis, and finalization must be performed later. Because partitionwise grouping or aggregation can use significantly more CPU time and memory during planning, the default is off.

enable_seqscan (boolean)

쿼리 플래너의 sequential scan plan types 사용을 활성화 또는 비활성화한다. sequential scans를 완전히 억제하는 것은 어렵지만 이 변수를 해제하면 사용 가능한 다른 방법이 있는 경우 플래너가 하나를 사용하는 것이 방지된다. 기본값은 on이다.

enable_sort (boolean)

쿼리 플래너의 explicit sort steps 사용을 활성화 또는 비활성화한다. explicit sorts를 완전히 억제하는 것은 어렵지만 이 변수를 해제하면 사용 가능한 다른 방법이 있는 경우 플래너가 하나를 사용하는 것이 방지된다. 기본값은 on이다.

enable_tidscan (boolean)

쿼리 플래너의 TID scan plan types 사용을 활성화 또는 비활성화한다. 기본값은 on이다.

19.7.2. 플래너 비용 상수

이 절에서 설명하는 cost 변수는 임의의 규모로 계산된다. 동일한 계수로 상향 또는 하향되는 상대적인 값만 플래너의 선택으로 바뀌지 않는다. 기본적으로, 이러한 비용 변수는 순차적 페이지 가져오기 비용을 근거로 한다. 즉, seq_page_cost는 인습적으로 1.0으로 설정되며, 다른 비용 변수는 그것을 기준으로 설정된다. 그러나 사용자가 원한다면 특정 머신에서 밀리초 단위의 실제 실행 시간 같이 다른 스케일을 사용할 수도 있다.

참고

아쉽게도 비용 변수에 대한 이상적인 값을 결정하는 제대로 정의된(well-defined) 방법은 없다. 특정한 설치가 수신하는 전체 쿼리 믹스에 대한 평균으로 처리하는 것이 최선이다. 이것은 몇 가지 경험에 비추어 값을 변경하는 것은 매우 위험할 수 있음을 의미한다.

seq_page_cost (floating point)

플래너가 예상한, 순차 가져오기 시리즈의 일부분인 디스크 페이지 가져오기 비용을 설정한다. 기본값은 1.0이다. 이 값은 동일한 이름의 테이블스페이스 매개 변수 설정에 의해 특수한 테이블스페이스의 테이블과 인덱스를 오버라이드할 수 있다(ALTER TABLESPACE 참조).

random_page_cost (floating point)

플래너가 예상한, 비순차적으로 가져온 디스크 페이지의 처리 비용을 설정한다. 기본값은 4.0이다. 이 값은 동일한 이름의 테이블스페이스 매개 변수 설정에 의해 특수한 테이블스페이스의 테이블과 인덱스를 오버라이드할 수 있다(ALTER TABLESPACE 참조).

이 값을 seq_page_cost에 비례하여 줄이면 시스템이 인덱스 스캔 쪽으로 치우치게 된다. 이 값을 늘리면 인덱스 스캔이 좀 더 비싸진다. 양쪽 값을 함께 늘리거나 줄여서 CPU 비용에 비례하여 디스크 I/O 비용의 중요도를 변경할 수 있다. 이것은 이후의 매개 변수에서 설명된다.

기계적 디스크 저장소에 대한 랜덤 액세스는 일반적으로 순차 액세스보다 4배 이상 비싸다. 그러나 인덱싱된 읽기 같이 디스크에 대한 랜덤 액세스 대부분은 캐시에서 일어나므로 작은 기본값이 사용된다(4.0). 랜덤 읽기의 90%는 캐싱되는 것으로 예상되는 반면, 기본값은 순차보다 모델링 랜덤 액세스가 40배 느린 것으로 생각될 수 있다.

사용자의 작업 부하에서 90%의 캐시율이 잘못된 가정인 경우 random_page_cost를 늘려서 랜덤 저장소 읽기의 실제 비용이 반영되도록 할 수 있다. 그에 따라, 총 서버 메모리보다 데이터베이스가 작아서 데이터가 완전히 캐시되는 경우 random_page_cost를 줄이는 것이 적절할 수 있다. SSD 디스크 같이 랜덤 읽기 비용이 시퀀스에 비해 상대적으로 낮은 저장소는 더 낮은 random_page_cost 값으로 지정하는 것이 더 좋을 것이다. 예, 1.1

작은 정보

random_page_costseq_page_cost 미만으로 설정하는 것이 시스템에서 허용되더라도 실제로는 그렇게 하는 것이 합리적이지 않다. 단, 데이터베이스 전체가 RAM에 캐치되는 경우에는 시퀀스 밖 페이지를 손대는 것에 대한 패널티가 없으므로 동일하게 설정하는 것은 괜찮다. 또한 과도하게 캐시되는 데이터베이스에서 RAM에 이미 있는 페이지를 가져오는 비용이 일반적인 상태의 것보다 훨씬 적으므로 사용자는 CPU 매개 변수에 비례하여 양쪽 값을 줄여야 한다.

cpu_tuple_cost (floating point)

플래너가 예상한 쿼리 도중 각 행의 처리 비용을 설정한다. 기본값은 0.01이다.

cpu_index_tuple_cost (floating point)

플래너가 예상한 인덱스 스캔 도중 각 인덱스 항목의 처리 비용을 설정한다. 기본값은 0.005이다.

cpu_operator_cost (floating point)

플래너가 예상한, 쿼리 도중 실행된 각 연산자 또는 함수의 처리 비용을 설정한다. 기본값은 0.0025이다.

parallel_setup_cost (floating point)

병렬 작업 프로세스의 실행 비용에 대한 플래너 추정치. 기본 값은 1000.

parallel_tuple_cost (floating point)

병렬 작업 프로세스가 다른 프로세스에게 하나의 튜플을 전송하는 플래너의 비용 추정치. 기본 값은 0.1.

min_parallel_table_scan_size (integer)

Sets the minimum amount of table data that must be scanned in order for a parallel scan to be considered. For a parallel sequential scan, the amount of table data scanned is always equal to the size of the table, but when indexes are used the amount of table data scanned will normally be less. If this value is specified without units, it is taken as blocks, that is BLCKSZ bytes, typically 8kB. The default is 8 megabytes (8MB).

min_parallel_index_scan_size (integer)

Sets the minimum amount of index data that must be scanned in order for a parallel scan to be considered. Note that a parallel index scan typically won't touch the entire index; it is the number of pages which the planner believes will actually be touched by the scan which is relevant. This parameter is also used to decide whether a particular index can participate in a parallel vacuum. See VACUUM. If this value is specified without units, it is taken as blocks, that is BLCKSZ bytes, typically 8kB. The default is 512 kilobytes (512kB).

effective_cache_size (integer)

단일 쿼리에 사용할 수 있는 디스크 캐시의 효율적인 크기에 대한 플래너의 가정을 설정한다. 이것은 인덱스를 사용하는 비용 추정에 반영된다. 값이 클수록 인덱스 스캔이 사용될 가능성이 높다. 값이 작을수록 순차 스캔이 사용될 가능성이 높다. 이 매개 변수를 설정하는 경우 PostgreSQL의 공유 버퍼와, PostgreSQL 데이터 파일에 사용되는 커널의 디스크 캐시 부분을 모두 고려해야 한다. 자료가 두 영역에 같이 있을 수 있기 때문이다. 또한 사용 가능한 공간을 공유해야 하므로 서로 다른 테이블에 대해 예상되는 동시 쿼리 수도 고려해야 한다. 이 매개 변수는 PostgreSQL에 의해 할당된 공유 메모리 크기에는 효과가 없으며, 커널 디스크 캐시도 예약하지 않는다. 추정용으로만 사용된다. 또한 시스템은 디스크 캐시에 쿼리 간 데이터가 잔류할 것이라고 가정하지 않는다. If this value is specified without units, it is taken as blocks, that is BLCKSZ bytes, typically 8kB. The default is 4 gigabytes (4GB). (If BLCKSZ is not 8kB, the default value scales proportionally to it.)

jit_above_cost (floating point)

Sets the query cost above which JIT compilation is activated, if enabled (see 31장). Performing JIT costs planning time but can accelerate query execution. Setting this to -1 disables JIT compilation. The default is 100000.

jit_inline_above_cost (floating point)

Sets the query cost above which JIT compilation attempts to inline functions and operators. Inlining adds planning time, but can improve execution speed. It is not meaningful to set this to less than jit_above_cost. Setting this to -1 disables inlining. The default is 500000.

jit_optimize_above_cost (floating point)

Sets the query cost above which JIT compilation applies expensive optimizations. Such optimization adds planning time, but can improve execution speed. It is not meaningful to set this to less than jit_above_cost, and it is unlikely to be beneficial to set it to more than jit_inline_above_cost. Setting this to -1 disables expensive optimizations. The default is 500000.

19.7.3. 유전 쿼리 최적화

유전 쿼리 최적화(Genetic Query Optimization, GEQO)는 경험적 추론 방법 검색을 사용하여 최적의 쿼리 실행계획을 선택하는 알고리즘이다. 이것은 최적의 실행 계획을 찾는 비용이 많이 드는 일반 알고리즘보다 적은 비용으로, 복잡한 쿼리(다수의 관계 조인)의 실행 계획을 짜는 시간을 줄인다. 자세한 내용은 59장을 참조 바란다.

geqo (boolean)

모든 쿼리에 대해서 이 기능을 사용할지 지정한다. 기본값은 on이다. 보통은 운영 중 해제하지 않는 것이 최선이며 geqo_threshold 변수는 좀 더 세분화된 GEQO 제어를 제공한다.

geqo_threshold (integer)

지정한 만큼의 FROM 항목 이상일 때, GEQO 기능을 사용한다. (FULL OUTER JOIN 구문은 하나의 FROM 항목으로 계산된다.) 기본값은 12이다. 단순 쿼리의 경우는 일반적으로 정규, 소모성 검색 실행계획기를 사용하는 것이 낫지만, 테이블이 다수 있는 쿼리의 경우 소모성 검색은 너무 오래 걸리며, 차선의 실행계획을 선택하는 것보다 더 오래 걸릴 수도 있다. 따라서 쿼리 크기에 대한 임계값은 GEQO 사용 관리에 편리한 방법이다.

geqo_effort (integer)

GEQO에서 작업할 최적 쿼리 실행 계획을 찾는 시간과 품질을 조정하는 값이다. 이 변수는 1 ~ 10 사이의 정수형이여야 한다. 기본값은 5이다. 값이 클수록 실행 계획을 짜는 시간이 늘어나지만, 효율적인 쿼리 실행 계획이 선택될 가능성도 높아진다.

geqo_effort가 직접 하는 일은 실제로 없다. GEQO 동작에 영향을 미치는 다른 변수에 대한 기본 값을 계산하는 데에만 이용된다(아래에 설명). 원한다면 그 대신 다른 매개 변수를 직접 설정할 수 있다.

geqo_pool_size (integer)

GEQO에서 사용되는 풀 크기를 제어한다. 풀 크기는 만드는 실행 계획 종류의 수이다. 이것은 최소 2 이상의 유용한 값이어야 하며, 일반적으로 100 ~ 1000이다. 0(기본값)으로 설정되면 적정값이 geqo_effort 값과 쿼리에서 사용하는 테이블 수를 고려하여 자동 계산된다.

geqo_generations (integer)

알고리즘 반복 숫자이자, GEQO에서 사용되는 생성 수를 제어한다. 이것은 최소 1 이상이어야 하며, 유용한 값은 풀 크기와 동일한 범위 내이다. 0(기본값)으로 설정되면 적정값이 geqo_pool_size 값에 따른다.

geqo_selection_bias (floating point)

GEQO에 의해 사용되는 선택 편향 관련 작업을 제어한다. 선택 편향이란 자연 선택 기준값이 된다. 값은 1.50 ~ 2.00일 수 있으며, 기본값 2.00.

geqo_seed (floating point)

조인 순서 검색 공간의 랜덤 경로를 선택하기 위해 GEQO에 의한 난수 발생기의 기본값을 제어한다. 값은 0(기본값) ~ 1일 수 있다. 값을 변경하면 탐색할 조인 경로 집합이 바뀌고 결과적으로 발견된 최상의 경로가 좋을 수도 있고 나쁠 수도 있다.

19.7.4. 실행 계획기 관련 기타 옵션들

default_statistics_target (integer)

ALTER TABLE SET STATISTICS를 통해 설정된 칼럼 특정 타겟 없이, 테이블 칼럼에 대한 기본 통계 타겟을 설정한다. 큰 값을 설정하면 ANALYZE를 수행하는 데 필요한 시간이 늘어나지만 플래너 평가 수준을 높일 수 있다. 기본값은 100이다. PostgreSQL 쿼리 플래너에 의한 통계 사용에 대한 내용은 14.2절을 참조 바란다.

constraint_exclusion (enum)

쿼리 최적화를 위해 쿼리 플래너의 테이블 제약 조건을 제어한다. constraint_exclusion의 허용 값은 on(모든 테이블에 대해 제약 조건 검사), off(제약 조건 검사 안함) 및 partition (상속 자식 테이블 및 UNION ALL 하위 쿼리에 대해서만 제약 조건 검사)이다. partition은 기본 설정이다. 이 설정은 옛부터 사용했던 상속 테이블 성능을 높이는데 가끔 사용된다.

이 매개 변수가 이것을 특정 테이블에 대해 허용하면 플래너가 쿼리 조건을 테이블의 CHECK 제약 조건과 비교하고 제약 조건에 위배되는 테이블을 검색하는 것은 생략한다. 예를 들면:

CREATE TABLE parent(key integer, ...);
CREATE TABLE child1000(check (key between 1000 and 1999)) INHERITS(parent);
CREATE TABLE child2000(check (key between 2000 and 2999)) INHERITS(parent);
...
SELECT * FROM parent WHERE key = 2400;

제약 조건 배제가 활성화되면 이 SELECT는 성능 개선을 위해 child1000을 일절 스캔하지 않는다.

현재, 제약 조건 배제는 옛부터 사용했던 상속 기반 테이블 파티션에 주로 사용되는 경우에만 기본값으로 활성화된다. 모든 테이블에 대해 활성화되며, 간단한 쿼리에도 눈에 띄게 플래닝 오버헤드가 가중되어 간단한 쿼리의 장점이 상쇄된다. 전통적인 상속 기반 파티션된 테이블이 없을 경우 전적으로 해제하는 것이 좋다. (Note that the equivalent feature for partitioned tables is controlled by a separate parameter, enable_partition_pruning.)

제약 사항 배제 기반 파티셔닝에 대한 자세한 내용은 5.11.5절을 참조 바란다.

cursor_tuple_fraction (floating point)

검색할 커서 행의 분할에 대한 플래너의 추정치를 설정한다. 기본값은 0.1이다. 값이 작을수록 플래너가 커서에 대해 fast start 플랜을 사용하도록 유도되고, 그러면 전체 행을 가져오느라 시간이 오래 걸리는 와중에 처음 몇 개의 행만 빠르게 검색된다. 값이 클수록 총 예상 시간이 중요해진다. 최대 설정 1.0에서는 커서가 정확히 일반 쿼리처럼 플랜되어 총 예상 시간만 고려되고, 첫 번째 행을 얼마나 빨리 가져오는지는 고려하지 않는다.

from_collapse_limit (integer)

결과로 나온 FROM 목록에 이 숫자만큼의 항목이 없을 경우 플래너가 하위 쿼리를 상위 쿼리에 병합한다. 값이 작을수록 플래닝 시간은 짧아지지만 하위 쿼리 플랜이 나올 수 있다. 기본값은 8이다. 자세한 내용은 14.3절을 참조 바란다.

이 값을 geqo_threshold 이상으로 설정하면 geqo 플래너의 사용이 트리거되어 결과적으로 최적화되지 않은 플랜이 된다. 19.7.3절을 참조 바란다.

jit (boolean)

Determines whether JIT compilation may be used by PostgreSQL, if available (see 31장). The default is on.

join_collapse_limit (integer)

결과 목록이 이 항목에 미치지 못할 경우 플래너는 명시적 JOIN 구문(FULL JOIN 제외)을 FROM 항목으로 재작성한다. 값이 작을수록 플래닝 시간은 짧아지지만 하위 쿼리 플랜이 나올 수 있다.

기본적으로 이 변수는 from_collapse_limit와 동일하게 설정되며, 대부분의 사용에 적합하다. 1로 설정하면 명시적 JOIN의 재정렬이 방지된다. 따라서 이 쿼리에서 지정된 명시적 조인 순서는 관계가 조인되는 실제 순서가 된다. 쿼리 플래너가 항상 최적의 조인 순서를 선택하는 것은 아니므로 고급 사용자는 이 변수를 임시로 1로 선택한 다음, 원하는 조인 순서를 명시적으로 지정할 수 있다. 자세한 내용은 14.3절을 참조 바란다.

이 값을 geqo_threshold 이상으로 설정하면 GEQO 플래너의 사용이 트리거되어 결과적으로 최적화되지 않은 플랜이 된다. 19.7.3절을 참조 바란다.

parallel_leader_participation (boolean)

Allows the leader process to execute the query plan under Gather and Gather Merge nodes instead of waiting for worker processes. The default is on. Setting this value to off reduces the likelihood that workers will become blocked because the leader is not reading tuples fast enough, but requires the leader process to wait for worker processes to start up before the first tuples can be produced. The degree to which the leader can help or hinder performance depends on the plan type, number of workers and query duration.

force_parallel_mode (enum)

병렬 쿼리의 사용은 더 이상 성능 향상이 기대되지 않는 쿼리를 테스트하는 목적으로 사용될 수 있다. force_parallel_mode 값은 off (성능 향상이 예상될 경우에만 병렬 처리 사용), on (안전하다고 생각되는 경우에 모든 쿼리에 병렬 처리 사용), regress (on과 같지만 아래 설명과 같이 추가 설정 가능)이 사용 가능하다.

on이면, 안전할 경우 모든 쿼리의 실행 계획 상단에 Gather 노드가 추가되며 병렬 작업자의 내부에 쿼리가 실행된다. (이 값이 on이면)병렬 작업자가 작동 가능하지 않거나 사용이 불가능 할 때라도, 병렬처리에서 서브 트랜잭션 시작과 같은 금지된 작업은 플래너가 쿼리가 실패할 것이라고 생각되지 않는 한 사용하지 못한다. 이 옵션이 설정되었을 때, 작업이 실패하거나 예상치 못한 결과가 발생할 경우 쿼리에 의해 사용되는 몇몇 함수는 PARALLEL UNSAFE(또는 PARALLEL RESTRICTED ) 옵션을 지정해야할 필요가 있다.

regresson의 기능과 함께 추가적인 효과가 있으며, 자동화된 회귀 테스트를 원활히 할 목적을 사용한다. 병렬 작업자의 메시지는 context 라인에 그것이 가리키는 것을 포함하지만 regress로 설정할 경우 병렬 작업이 실행하지 않은 것처럼 출력된다. 이 설정으로 Gather 노드가 추가한 실행계획을 EXPLAIN 출력에 숨겨 병렬처리가 off된 것처럼 출력 값이 동일하다.

plan_cache_mode (enum)

Prepared statements (either explicitly prepared or implicitly generated, for example by PL/pgSQL) can be executed using custom or generic plans. Custom plans are made afresh for each execution using its specific set of parameter values, while generic plans do not rely on the parameter values and can be re-used across executions. Thus, use of a generic plan saves planning time, but if the ideal plan depends strongly on the parameter values then a generic plan may be inefficient. The choice between these options is normally made automatically, but it can be overridden with plan_cache_mode. The allowed values are auto (the default), force_custom_plan and force_generic_plan. This setting is considered when a cached plan is to be executed, not when it is prepared. For more information see PREPARE.