From 07ee6a8a2b053a671a2d4a8f8ad47f1eb991e71f Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Wed, 8 Nov 2023 08:31:51 +0900 Subject: [PATCH] Revert "Fix handling of unavailable indexes in Scan hints" This reverts commit a3646e1b073c, that we have found to do more weird plan manipulations by ignoring in some cases Parallel hints when they should not. The behavior before this commit has also some historical weirdness, but impacting the stability of plans is not a good idea in stable branches, so for now this change is reverted. Additional regression tests will be added on HEAD to track all the behaviors around parallel hints that have been seen, while keeping the new plan changes only for 17~ and new major release integration. Per discussion on #164. Backpatch-through: 13 --- expected/pg_hint_plan.out | 126 +++++++++++++++++++------------------- expected/ut-S.out | 62 +++++++++---------- pg_hint_plan.c | 77 ++++------------------- 3 files changed, 107 insertions(+), 158 deletions(-) diff --git a/expected/pg_hint_plan.out b/expected/pg_hint_plan.out index 021c561e..7785d655 100644 --- a/expected/pg_hint_plan.out +++ b/expected/pg_hint_plan.out @@ -5571,15 +5571,15 @@ EXPLAIN (COSTS false) SELECT * FROM t5 WHERE t5.id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(t5 no_exist) +not used hint: duplication hint: error hint: - QUERY PLAN ----------------------------------------------------------------------------------------- - Index Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+IndexScan(t5 t5_id1 t5_id2)*/ @@ -5619,15 +5619,15 @@ EXPLAIN (COSTS false) SELECT * FROM t5 WHERE t5.id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(t5 no_exist5 no_exist2) +not used hint: duplication hint: error hint: - QUERY PLAN ----------------------------------------------------------------------------------------- - Index Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) -- outer inner @@ -6746,8 +6746,8 @@ LOG: available indexes for IndexScan(p2_c3_c1): LOG: available indexes for IndexScan(p2_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(p2 p2_val) +not used hint: duplication hint: error hint: @@ -6924,8 +6924,8 @@ LOG: available indexes for IndexScan(p2_c1_c1): LOG: available indexes for IndexScan(p2_c1_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(p2 no_exist) +not used hint: duplication hint: error hint: @@ -7287,15 +7287,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexScanRegexp(t5 t5[^_].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ IndexScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7303,15 +7303,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ IndexScan(t5 t5_id[0-9].*)*/ @@ -7319,15 +7319,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexScan(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(t5 t5_id[0-9].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ IndexOnlyScanRegexp(t5 t5_[^i].*)*/ @@ -7367,15 +7367,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScanRegexp(t5 t5[^_].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ IndexOnlyScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7383,15 +7383,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ IndexOnlyScan(t5 t5_id[0-9].*)*/ @@ -7399,15 +7399,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for IndexOnlyScan(t5): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScan(t5 t5_id[0-9].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ BitmapScanRegexp(t5 t5_[^i].*)*/ @@ -7451,15 +7451,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: BitmapScanRegexp(t5 t5[^_].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ BitmapScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab)*/ @@ -7467,15 +7467,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScanRegexp(t5): LOG: pg_hint_plan: used hint: -not used hint: BitmapScanRegexp(t5 ^.*t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) /*+ BitmapScan(t5 t5_id[0-9].*)*/ @@ -7483,15 +7483,15 @@ EXPLAIN (COSTS false) SELECT id FROM t5 WHERE id = 1; LOG: available indexes for BitmapScan(t5): LOG: pg_hint_plan: used hint: -not used hint: BitmapScan(t5 t5_id[0-9].*) +not used hint: duplication hint: error hint: - QUERY PLAN ---------------------------------------------------------------------------------------------- - Index Only Scan using t5_idaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa on t5 - Index Cond: (id = 1) + QUERY PLAN +-------------------- + Seq Scan on t5 + Filter: (id = 1) (2 rows) -- Inheritance @@ -7614,8 +7614,8 @@ LOG: available indexes for IndexScanRegexp(p1_c3_c1): LOG: available indexes for IndexScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexScanRegexp(p1 p1[^_].*) +not used hint: duplication hint: error hint: @@ -7655,8 +7655,8 @@ LOG: available indexes for IndexScan(p1_c3_c1): LOG: available indexes for IndexScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(p1 p1_.*val2.*) +not used hint: duplication hint: error hint: @@ -7778,8 +7778,8 @@ LOG: available indexes for IndexOnlyScanRegexp(p1_c3_c1): LOG: available indexes for IndexOnlyScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScanRegexp(p1 p1[^_].*) +not used hint: duplication hint: error hint: @@ -7819,8 +7819,8 @@ LOG: available indexes for IndexOnlyScan(p1_c3_c1): LOG: available indexes for IndexOnlyScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScan(p1 p1_.*val2.*) +not used hint: duplication hint: error hint: @@ -7960,8 +7960,8 @@ LOG: available indexes for BitmapScanRegexp(p1_c3_c1): LOG: available indexes for BitmapScanRegexp(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: BitmapScanRegexp(p1 p1[^_].*) +not used hint: duplication hint: error hint: @@ -8001,8 +8001,8 @@ LOG: available indexes for BitmapScan(p1_c3_c1): LOG: available indexes for BitmapScan(p1_c3_c2): LOG: pg_hint_plan: used hint: -not used hint: BitmapScan(p1 p1_.*val2.*) +not used hint: duplication hint: error hint: diff --git a/expected/ut-S.out b/expected/ut-S.out index 6a9dd66b..4e364517 100644 --- a/expected/ut-S.out +++ b/expected/ut-S.out @@ -4534,8 +4534,8 @@ error hint: LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(ti1 not_exist) +not used hint: duplication hint: error hint: @@ -4543,8 +4543,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) - Index Cond: (c1 = 100) + Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) + Filter: (c1 = 100) -- No. S-3-5-5 \o results/ut-S.tmpout @@ -4552,8 +4552,8 @@ error hint: LOG: available indexes for BitmapScan(ti1): LOG: pg_hint_plan: used hint: -not used hint: BitmapScan(ti1 not_exist) +not used hint: duplication hint: error hint: @@ -4561,8 +4561,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) - Index Cond: (c1 = 100) + Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) + Filter: (c1 = 100) -- No. S-3-5-6 \o results/ut-S.tmpout @@ -4570,8 +4570,8 @@ error hint: LOG: available indexes for IndexOnlyScan(ti1): LOG: pg_hint_plan: used hint: -not used hint: IndexOnlyScan(ti1 not_exist) +not used hint: duplication hint: error hint: @@ -4579,8 +4579,8 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Index Scan using ti1_hash on ti1 (cost=xxx..xxx rows=1 width=xxx) - Index Cond: (c1 = 100) + Seq Scan on ti1 (cost={inf}..{inf} rows=1 width=xxx) + Filter: (c1 = 100) -- No. S-3-5-7 EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE t1.c1 = 1; @@ -5283,11 +5283,11 @@ error hint: Append (cost=xxx..xxx rows=4 width=xxx) -> Index Scan using p1_i2 on p1 p1_1 (cost=xxx..xxx rows=1 width=xxx) Index Cond: (c2 = 1) - -> Seq Scan on p1c1 p1_2 (cost=xxx..xxx rows=1 width=xxx) + -> Seq Scan on p1c1 p1_2 (cost={inf}..{inf} rows=1 width=xxx) Filter: (c2 = 1) - -> Seq Scan on p1c2 p1_3 (cost=xxx..xxx rows=1 width=xxx) + -> Seq Scan on p1c2 p1_3 (cost={inf}..{inf} rows=1 width=xxx) Filter: (c2 = 1) - -> Seq Scan on p1c3 p1_4 (cost=xxx..xxx rows=1 width=xxx) + -> Seq Scan on p1c3 p1_4 (cost={inf}..{inf} rows=1 width=xxx) Filter: (c2 = 1) -- No. S-3-10-5 @@ -5307,12 +5307,12 @@ error hint: \! sql/maskout.sh results/ut-S.tmpout QUERY PLAN ---------------- - Append (cost=xxx..xxx rows=3 width=xxx) - -> Seq Scan on p2 p2_1 (cost=xxx..xxx rows=1 width=xxx) + Append (cost={inf}..{inf} rows=3 width=xxx) + -> Seq Scan on p2 p2_1 (cost={inf}..{inf} rows=1 width=xxx) Filter: (c1 = 1) -> Index Scan using p2c1_pkey on p2c1 p2_2 (cost=xxx..xxx rows=1 width=xxx) Index Cond: (c1 = 1) - -> Seq Scan on p2c1c1 p2_3 (cost=xxx..xxx rows=1 width=xxx) + -> Seq Scan on p2c1c1 p2_3 (cost={inf}..{inf} rows=1 width=xxx) Filter: (c1 = 1) ---- @@ -6010,15 +6010,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScanRegexp(ti1): LOG: pg_hint_plan: used hint: -not used hint: IndexScanRegexp(ti1 no.*_exist) +not used hint: duplication hint: error hint: - QUERY PLAN --------------------------------- - Index Scan using ti1_i4 on ti1 - Index Cond: (c2 = 1) + QUERY PLAN +-------------------- + Seq Scan on ti1 + Filter: (c2 = 1) (2 rows) -- No. S-3-14-4 @@ -6070,8 +6070,8 @@ LOG: available indexes for IndexScanRegexp(p1): LOG: available indexes for IndexScanRegexp(p1c1): LOG: pg_hint_plan: used hint: -not used hint: IndexScanRegexp(p1 no.*_exist) +not used hint: duplication hint: error hint: @@ -6110,15 +6110,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(ti1 not_exist) +not used hint: duplication hint: error hint: - QUERY PLAN --------------------------------- - Index Scan using ti1_i4 on ti1 - Index Cond: (c2 = 1) + QUERY PLAN +-------------------- + Seq Scan on ti1 + Filter: (c2 = 1) (2 rows) -- No. S-3-15-3 @@ -6161,15 +6161,15 @@ EXPLAIN (COSTS false) SELECT * FROM s1.ti1 WHERE c2 = 1; LOG: available indexes for IndexScan(ti1): LOG: pg_hint_plan: used hint: -not used hint: IndexScan(ti1 not_exist1 not_exist2) +not used hint: duplication hint: error hint: - QUERY PLAN --------------------------------- - Index Scan using ti1_i4 on ti1 - Index Cond: (c2 = 1) + QUERY PLAN +-------------------- + Seq Scan on ti1 + Filter: (c2 = 1) (2 rows) DELETE FROM pg_db_role_setting WHERE setrole = (SELECT oid FROM pg_roles WHERE rolname = current_user); diff --git a/pg_hint_plan.c b/pg_hint_plan.c index e77fd6ec..0444b5de 100644 --- a/pg_hint_plan.c +++ b/pg_hint_plan.c @@ -3399,25 +3399,15 @@ regexpeq(const char *s1, const char *s2) } -/* - * Filter out indexes instructed in the hint as not to be used. - * - * This routine is used in relationship with the scan method enforcement, and - * it returns true to allow the follow-up scan method to be enforced, and false - * to prevent the scan enforcement. Currently, this code will not enforce - * the scan enforcement if *all* the indexes available to a relation have been - * discarded. - */ -static bool +/* Remove indexes instructed not to use by hint. */ +static void restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, - bool using_parent_hint) + bool using_parent_hint) { ListCell *cell; StringInfoData buf; RangeTblEntry *rte = root->simple_rte_array[rel->relid]; Oid relationObjectId = rte->relid; - List *unused_indexes = NIL; - bool restrict_result; /* * We delete all the IndexOptInfo list and prevent you from being usable by @@ -3430,20 +3420,18 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, rel->indexlist = NIL; hint->base.state = HINT_STATE_USED; - return true; + return; } /* * When a list of indexes is not specified, we just use all indexes. */ if (hint->indexnames == NIL) - return true; + return; /* * Leaving only an specified index, we delete it from a IndexOptInfo list - * other than it. However, if none of the specified indexes are available, - * then we keep all the indexes and skip enforcing the scan method. i.e., - * we skip the scan hint altogether for the relation. + * other than it. */ if (debug_level > 0) initStringInfo(&buf); @@ -3637,42 +3625,11 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, } if (!use_index) - unused_indexes = lappend_oid(unused_indexes, info->indexoid); + rel->indexlist = foreach_delete_current(rel->indexlist, cell); pfree(indexname); } - /* - * Update the list of indexes available to the IndexOptInfo based on what - * has been discarded previously. - * - * If the hint has no matching indexes, skip applying the hinted scan - * method. For example if an IndexScan hint does not have any matching - * indexes, we should not enforce an enable_indexscan. - */ - if (list_length(unused_indexes) < list_length(rel->indexlist)) - { - foreach (cell, unused_indexes) - { - Oid final_oid = lfirst_oid(cell); - ListCell *l; - - foreach (l, rel->indexlist) - { - IndexOptInfo *info = (IndexOptInfo *) lfirst(l); - - if (info->indexoid == final_oid) - rel->indexlist = foreach_delete_current(rel->indexlist, l); - } - } - - restrict_result = true; - } - else - restrict_result = false; - - list_free(unused_indexes); - if (debug_level > 0) { StringInfoData rel_buf; @@ -3699,8 +3656,6 @@ restrict_indexes(PlannerInfo *root, ScanMethodHint *hint, RelOptInfo *rel, pfree(buf.data); pfree(rel_buf.data); } - - return restrict_result; } /* @@ -3889,6 +3844,8 @@ setup_hint_enforcement(PlannerInfo *root, RelOptInfo *rel, { ScanMethodHint * pshint = current_hint_state->parent_scan_hint; + pshint->base.state = HINT_STATE_USED; + /* Apply index mask in the same manner to the parent. */ if (pshint->indexnames) { @@ -3934,22 +3891,14 @@ setup_hint_enforcement(PlannerInfo *root, RelOptInfo *rel, { bool using_parent_hint = (shint == current_hint_state->parent_scan_hint); - bool restrict_result; ret |= HINT_BM_SCAN_METHOD; - /* restrict unwanted indexes */ - restrict_result = restrict_indexes(root, shint, rel, using_parent_hint); + /* Setup scan enforcement environment */ + setup_scan_method_enforcement(shint, current_hint_state); - /* - * Setup scan enforcement environment - * - * This has to be called after restrict_indexes(), that may decide to - * skip the scan method enforcement depending on the index restrictions - * applied. - */ - if (restrict_result) - setup_scan_method_enforcement(shint, current_hint_state); + /* restrict unwanted inexes */ + restrict_indexes(root, shint, rel, using_parent_hint); if (debug_level > 1) {