테이블 파티션 지원 - Amazon Aurora

테이블 파티션 지원

Aurora PostgreSQL 쿼리 계획 관리(QPM)는 다음 버전에서 선언적 테이블 파티셔닝을 지원합니다.

  • 15.3 이상의 15 버전

  • 14.8 이상의 14 버전

  • 13.11 이상의 13 버전

자세한 내용은 테이블 파티셔닝을 참조하세요.

테이블 파티션 설정

Aurora PostgreSQL QPM에서 테이블 파티션을 설정하려면 다음 작업을 수행합니다.

  1. DB 클러스터 파라미터 그룹에서 apg_plan_mgmt.plan_hash_version을 3 이상으로 설정합니다.

  2. 쿼리 계획 관리를 사용하고 apg_plan_mgmt.dba_plans 보기에 항목이 있는 데이터베이스로 이동합니다.

  3. apg_plan_mgmt.validate_plans('update_plan_hash')를 호출하여 계획 테이블의 plan_hash 값을 업데이트합니다.

  4. apg_plan_mgmt.dba_plans 보기에 항목이 있으며 쿼리 계획 관리가 활성화된 모든 데이터베이스에 대해 2~3단계를 반복합니다.

이런 파라미터에 대한 자세한 내용은 Aurora PostgreSQL 쿼리 계획 관리를 위한 파라미터 참조 섹션을 참조하세요.

테이블 파티션에 대한 계획 캡처

QPM에서는 다양한 계획이 plan_hash 값으로 구분됩니다. plan_hash가 어떻게 변하는지 이해하려면 먼저 비슷한 종류의 계획을 이해해야 합니다.

계획이 동일한 것으로 간주되려면 Append 노드 수준에서 누적된 액세스 방법, 숫자 제거 인덱스 이름 및 숫자 제거 파티션 이름의 조합이 일정해야 합니다. 계획에서 액세스하는 특정 파티션은 중요하지 않습니다. 다음 예제에서는 파티션이 4개인 tbl_a 테이블이 생성됩니다.

postgres=>create table tbl_a(i int, j int, k int, l int, m int) partition by range(i); CREATE TABLE postgres=>create table tbl_a1 partition of tbl_a for values from (0) to (1000); CREATE TABLE postgres=>create table tbl_a2 partition of tbl_a for values from (1001) to (2000); CREATE TABLE postgres=>create table tbl_a3 partition of tbl_a for values from (2001) to (3000); CREATE TABLE postgres=>create table tbl_a4 partition of tbl_a for values from (3001) to (4000); CREATE TABLE postgres=>create index t_i on tbl_a using btree (i); CREATE INDEX postgres=>create index t_j on tbl_a using btree (j); CREATE INDEX postgres=>create index t_k on tbl_a using btree (k); CREATE INDEX

다음 계획은 쿼리에서 조회하는 파티션 수에 관계없이 단일 스캔 방법을 사용하여 tbl_a를 스캔하기 때문에 동일한 것으로 간주됩니다.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 999 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------- Seq Scan on tbl_a1 tbl_a Filter: ((i >= 990) AND (i <= 999) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (3 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (6 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a3 tbl_a_3 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (8 rows)

상위 수준에서 액세스 방법, 숫자 제거 인덱스 이름 및 숫자 제거 파티션 이름이 SeqScan tbl_a, IndexScan (i_idx) tbl_a이므로 다음 3가지 계획도 동일한 것으로 간주됩니다.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a2_i_idx on tbl_a2 tbl_a_2 Index Cond: ((i >= 990) AND (i <= 1100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (7 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (10 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a3 tbl_a_3 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a4_i_idx on tbl_a4 tbl_a_4 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (11 rows)

하위 파티션의 순서 및 발생 횟수에 관계없이 액세스 방법, 숫자 제거 인덱스 이름 및 숫자 제거 파티션 이름은 위의 각 계획에 대해 상위 수준에서 일정합니다.

그러나 다음 조건 중 하나라도 충족되면 계획이 다른 것으로 간주됩니다.

  • 계획에 추가 액세스 방법이 사용됩니다.

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Bitmap Heap Scan on tbl_a3 tbl_a_3 Recheck Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a3_i_idx Index Cond: ((i >= 990) AND (i <= 2100)) SQL Hash: 1553185667, Plan Hash: 1134525070 (11 rows)
  • 계획의 모든 액세스 방법이 더 이상 사용되지 않습니다.

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -694232056 (6 rows)
  • 인덱스 방법과 연결된 인덱스가 변경됩니다.

    postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Seq Scan on tbl_a1 tbl_a_1 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a2_j_idx on tbl_a2 tbl_a_2 Index Cond: (j < 9910) Filter: ((i >= 990) AND (i <= 1100) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993343726 (7 rows)

테이블 파티션 계획 적용

파티셔닝된 테이블에 대한 승인된 계획은 위치 대응과 함께 적용됩니다. 계획은 파티션에만 국한되지 않으며, 원래 쿼리에서 참조된 계획이 아닌 다른 파티션에도 적용할 수 있습니다. 또한 계획에는 원래 승인된 개요와 다른 수의 파티션에 액세스하는 쿼리에 적용할 수 있는 기능이 있습니다.

예를 들어 승인된 개요가 아래 계획에 대한 것이라면 다음과 같습니다.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) SQL Hash: 1553185667, Plan Hash: -993736942 (10 rows)

그런 다음 2개, 4개 이상의 파티션을 참조하는 SQL 쿼리에도 이 계획을 적용할 수 있습니다. 2개 및 4개 파티션 액세스에 대한 이러한 시나리오에서 발생할 수 있는 계획은 다음과 같습니다.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1100 and j < 9910 and k > 50; QUERY PLAN ---------------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 1100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1100) AND (j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (8 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a4 tbl_a_4 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (12 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 3100 and j < 9910 and k > 50; QUERY PLAN ---------------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 3100) AND (j < 9910) AND (k > 50)) -> Index Scan using tbl_a3_i_idx on tbl_a3 tbl_a_3 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) -> Index Scan using tbl_a4_i_idx on tbl_a4 tbl_a_4 Index Cond: ((i >= 990) AND (i <= 3100)) Filter: ((j < 9910) AND (k > 50)) Note: An Approved plan was used instead of the minimum cost plan. SQL Hash: 1553185667, Plan Hash: -993736942, Minimum Cost Plan Hash: -1873216041 (14 rows)

각 파티션마다 다른 액세스 방법을 사용하는 승인된 다른 계획을 고려해 보세요.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 2100 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 2100) AND (j < 9910) AND (k > 50)) -> Bitmap Heap Scan on tbl_a3 tbl_a_3 Recheck Cond: ((i >= 990) AND (i <= 2100)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a3_i_idx Index Cond: ((i >= 990) AND (i <= 2100)) SQL Hash: 1553185667, Plan Hash: 2032136998 (12 rows)

이 경우 두 파티션에서 읽어 들이는 계획은 실행되지 않습니다. 승인된 계획의 모든 조합(액세스 방법, 인덱스 이름)을 사용할 수 없으면 계획을 적용할 수 없습니다. 예를 들어 다음 계획에는 서로 다른 계획 해시가 있으며 이러한 경우에는 승인된 계획을 적용할 수 없습니다.

postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1900 and j < 9910 and k > 50; QUERY PLAN ------------------------------------------------------------------------- Append -> Bitmap Heap Scan on tbl_a1 tbl_a_1 Recheck Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a1_i_idx Index Cond: ((i >= 990) AND (i <= 1900)) -> Bitmap Heap Scan on tbl_a2 tbl_a_2 Recheck Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Bitmap Index Scan on tbl_a2_i_idx Index Cond: ((i >= 990) AND (i <= 1900)) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: 1553185667, Plan Hash: -568647260 (13 rows)
postgres=>explain (hashes true, costs false) select j, k from tbl_a where i between 990 and 1900 and j < 9910 and k > 50; QUERY PLAN -------------------------------------------------------------------------- Append -> Index Scan using tbl_a1_i_idx on tbl_a1 tbl_a_1 Index Cond: ((i >= 990) AND (i <= 1900)) Filter: ((j < 9910) AND (k > 50)) -> Seq Scan on tbl_a2 tbl_a_2 Filter: ((i >= 990) AND (i <= 1900) AND (j < 9910) AND (k > 50)) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: 1553185667, Plan Hash: -496793743 (8 rows)

이름 지정 규칙

QPM에서 선언적 파티셔닝된 테이블을 사용하여 계획을 적용하려면 상위 테이블, 테이블 파티션 및 인덱스에 대한 특정 이름 지정 규칙을 따라야 합니다.

  • 상위 테이블 이름 - 이 이름은 숫자만이 아니라 알파벳이나 특수 문자로 구분해야 합니다. 예를 들어 tA, tB 및 tC는 개별 상위 테이블에 사용할 수 있는 이름이지만, t1, t2 및 t3는 사용할 수 없습니다.

  • 개별 파티션 테이블 이름 - 동일한 상위 파티션의 파티션은 숫자만 달라야 합니다. 예를 들어 tA의 허용 가능한 파티션 이름은 tA1, tA2 또는 t1A, t2A나 여러 자리 숫자일 수 있습니다.

    문자, 특수 문자로 차이를 두면 계획 적용이 보장되지 않습니다.

  • 인덱스 이름 - 파티션 테이블 계층 구조에서 모든 인덱스의 이름이 고유하도록 해야 합니다. 즉, 이름에서 숫자가 아닌 부분이 달라야 합니다. 예를 들어 이름이 tA인 파티셔닝 테이블에 인덱스 이름이 tA_col1_idx1인 인덱스가 있는 경우 이름이 tA_col1_idx2인 다른 인덱스를 포함할 수 없습니다. 하지만 이름이 tA_a_col1_idx2인 인덱스는 포함할 수 있습니다. 이름에서 숫자가 아닌 부분이 고유하기 때문입니다. 이 규칙은 상위 테이블과 개별 파티션 테이블 모두에 생성된 인덱스에 적용됩니다.

위의 이름 지정 규칙을 준수하지 않을 경우 승인된 계획 적용이 실패할 수 있습니다. 다음은 실패한 적용의 예를 보여줍니다.

postgres=>create table t1(i int, j int, k int, l int, m int) partition by range(i); CREATE TABLE postgres=>create table t1a partition of t1 for values from (0) to (1000); CREATE TABLE postgres=>create table t1b partition of t1 for values from (1001) to (2000); CREATE TABLE postgres=>SET apg_plan_mgmt.capture_plan_baselines TO 'manual'; SET postgres=>explain (hashes true, costs false) select count(*) from t1 where i > 0; QUERY PLAN -------------------------------------------------------------------------- Aggregate -> Append -> Seq Scan on t1a t1_1 Filter: (i > 0) -> Seq Scan on t1b t1_2 Filter: (i > 0) SQL Hash: -1720232281, Plan Hash: -1010664377 (7 rows)
postgres=>SET apg_plan_mgmt.use_plan_baselines TO 'on'; SET postgres=>explain (hashes true, costs false) select count(*) from t1 where i > 1000; QUERY PLAN ------------------------------------------------------------------------- Aggregate -> Seq Scan on t1b t1 Filter: (i > 1000) Note: This is not an Approved plan. No usable Approved plan was found. SQL Hash: -1720232281, Plan Hash: 335531806 (5 rows)

두 계획이 동일하게 보일 수도 있지만 하위 테이블의 이름 때문에 Plan Hash 값이 다릅니다. 테이블 이름이 숫자만이 아닌 영문자에 따라 다양하므로 적용이 실패합니다.