diff --git a/src/gausskernel/optimizer/util/plancat.cpp b/src/gausskernel/optimizer/util/plancat.cpp index bee027445..bdc4fe5c7 100644 --- a/src/gausskernel/optimizer/util/plancat.cpp +++ b/src/gausskernel/optimizer/util/plancat.cpp @@ -251,11 +251,20 @@ void get_relation_info(PlannerInfo* root, Oid relationObjectId, bool inhparent, * mark the plan we are generating as transient. See * src/backend/access/heap/README.HOT for discussion. */ - if (index->indcheckxmin && !TransactionIdPrecedes(HeapTupleGetRawXmin(indexRelation->rd_indextuple), - u_sess->utils_cxt.TransactionXmin)) { - root->glob->transientPlan = true; - index_close(indexRelation, NoLock); - continue; + if (index->indcheckxmin) { + TransactionId xmin = HeapTupleGetRawXmin(indexRelation->rd_indextuple); + if (!TransactionIdPrecedes(xmin, u_sess->utils_cxt.TransactionXmin)) { + /* + * Since the TransactionXmin won't advance immediately(see CalculateLocalLatestSnapshot), + * we need to check CSN for the visibility. + */ + CommitSeqNo csn = TransactionIdGetCommitSeqNo(xmin, true, true, false); + if (csn >= u_sess->utils_cxt.CurrentSnapshot->snapshotcsn) { + root->glob->transientPlan = true; + index_close(indexRelation, NoLock); + continue; + } + } } info = makeNode(IndexOptInfo); diff --git a/src/gausskernel/runtime/executor/opfusion_util.cpp b/src/gausskernel/runtime/executor/opfusion_util.cpp index dc4787c95..20a1449ad 100755 --- a/src/gausskernel/runtime/executor/opfusion_util.cpp +++ b/src/gausskernel/runtime/executor/opfusion_util.cpp @@ -93,6 +93,10 @@ const char *getBypassReason(FusionType result) return "Bypass not executed because query used unsupported indexscan condition"; } + case NOBYPASS_ONLY_SUPPORT_BTREE_INDEX: { + return "Bypass not executed because only support btree index currently"; + } + case NOBYPASS_INDEXONLYSCAN_WITH_ORDERBY: { return "Bypass not executed because query used indexonlyscan with order by clause method"; } @@ -438,12 +442,14 @@ template FusionType checkFusionIndexScan(Node *n List *indexorderby = NULL; List *indexqual = NULL; List *qual = NULL; + Oid indexOid = InvalidOid; + Relation index = NULL; if (isonlyindex) { tarlist = ((IndexOnlyScan *)node)->scan.plan.targetlist; indexorderby = ((IndexOnlyScan *)node)->indexorderby; indexqual = ((IndexOnlyScan *)node)->indexqual; qual = ((IndexOnlyScan *)node)->scan.plan.qual; - + indexOid = ((IndexOnlyScan *)node)->indexid; if (indexorderby != NULL) { return NOBYPASS_INDEXONLYSCAN_WITH_ORDERBY; } @@ -452,12 +458,19 @@ template FusionType checkFusionIndexScan(Node *n indexorderby = ((IndexScan *)node)->indexorderby; indexqual = ((IndexScan *)node)->indexqual; qual = ((IndexScan *)node)->scan.plan.qual; - + indexOid = ((IndexScan *)node)->indexid; if (indexorderby != NULL) { return NOBYPASS_INDEXSCAN_WITH_ORDERBY; } } + index = index_open(indexOid, AccessShareLock); + if (index->rd_rel->relam != BTREE_AM_OID) { + index_close(index, AccessShareLock); + return NOBYPASS_ONLY_SUPPORT_BTREE_INDEX; + } + index_close(index, AccessShareLock); + ListCell *lc = NULL; if (is_dml == false) { diff --git a/src/include/opfusion/opfusion_util.h b/src/include/opfusion/opfusion_util.h index 9ec71f022..226209f2b 100644 --- a/src/include/opfusion/opfusion_util.h +++ b/src/include/opfusion/opfusion_util.h @@ -68,6 +68,7 @@ enum FusionType { NOBYPASS_UPSERT_NOT_SUPPORT, NOBYPASS_NO_INDEXSCAN, + NOBYPASS_ONLY_SUPPORT_BTREE_INDEX, NOBYPASS_INDEXSCAN_WITH_ORDERBY, NOBYPASS_INDEXSCAN_WITH_QUAL, NOBYPASS_INDEXSCAN_CONDITION_INVALID, diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index 37cf439d6..ecdaf0e65 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -619,10 +619,9 @@ EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) SELECT * FROM point_tbl WHERE f1 IS NULL; QUERY PLAN ----------------------------------------- - [Bypass] Index Scan using gpointind on point_tbl Index Cond: (f1 IS NULL) -(3 rows) +(2 rows) SELECT * FROM point_tbl WHERE f1 IS NULL; f1 @@ -2748,3 +2747,33 @@ drop index test_table_idx1; drop index test_table_col_idx1; drop table test_table; drop table test_table_col; +SET enable_seqscan=off; +reset enable_indexscan; +reset enable_bitmapscan; +DROP TABLE IF EXISTS ddl_index_visibility; +NOTICE: table "ddl_index_visibility" does not exist, skipping +CREATE TABLE ddl_index_visibility(id INT, first_name text, last_name text); +--insert data +INSERT INTO ddl_index_visibility SELECT id, md5(random()::text), md5(random()::text) FROM (SELECT * FROM generate_series(1,2000) AS id) AS x; +--this update will produce a HOT, then the next created index need to check xmin when using it(get_relation_info) +update ddl_index_visibility set first_name='+dw', last_name='dw_rt' where id = 698; +--create index, indcheckxmin will be true +create index ddl_index_visibility_idx on ddl_index_visibility USING btree(id); +--explain, should be BitmapHeapScan +explain(costs off) select * from ddl_index_visibility where id=698; + QUERY PLAN +----------------------------------------------------- + Bitmap Heap Scan on ddl_index_visibility + Recheck Cond: (id = 698) + -> Bitmap Index Scan on ddl_index_visibility_idx + Index Cond: (id = 698) +(4 rows) + +select * from ddl_index_visibility where id=698; + id | first_name | last_name +-----+------------+----------- + 698 | +dw | dw_rt +(1 row) + +reset enable_seqscan; +DROP TABLE ddl_index_visibility; diff --git a/src/test/regress/expected/gpi_bitmapscan.out b/src/test/regress/expected/gpi_bitmapscan.out index 7886ef28d..0a2313470 100644 --- a/src/test/regress/expected/gpi_bitmapscan.out +++ b/src/test/regress/expected/gpi_bitmapscan.out @@ -293,18 +293,20 @@ drop index test_part_bitmapand_ginst_btree_a_idx; CREATE UNIQUE INDEX ON test_part_bitmapand_ginst_btree (a); --bitmapand scan explain (costs off) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10; - QUERY PLAN ------------------------------------------------------------------------ + QUERY PLAN +--------------------------------------------------------------------------------------- Partition Iterator Iterations: 1 -> Partitioned Bitmap Heap Scan on test_part_bitmapand_ginst_btree - Recheck Cond: (keyword @> '''new'''::tsquery) - Filter: (a = 10) + Recheck Cond: ((keyword @> '''new'''::tsquery) AND (a = 10)) Selected Partitions: 1 - -> Partitioned Bitmap Index Scan on qq - Index Cond: (keyword @> '''new'''::tsquery) - Selected Partitions: 1 -(9 rows) + -> BitmapAnd + -> Partitioned Bitmap Index Scan on qq + Index Cond: (keyword @> '''new'''::tsquery) + Selected Partitions: 1 + -> Bitmap Index Scan on test_part_bitmapand_ginst_btree_a_tableoid_idx + Index Cond: (a = 10) +(11 rows) SELECT keyword FROM test_part_bitmapand_ginst_btree WHERE keyword @> 'new' and a = 10; keyword diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index 25c9bf2b5..281258396 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -968,3 +968,22 @@ drop index test_table_idx1; drop index test_table_col_idx1; drop table test_table; drop table test_table_col; + +SET enable_seqscan=off; +reset enable_indexscan; +reset enable_bitmapscan; + +DROP TABLE IF EXISTS ddl_index_visibility; +CREATE TABLE ddl_index_visibility(id INT, first_name text, last_name text); +--insert data +INSERT INTO ddl_index_visibility SELECT id, md5(random()::text), md5(random()::text) FROM (SELECT * FROM generate_series(1,2000) AS id) AS x; +--this update will produce a HOT, then the next created index need to check xmin when using it(get_relation_info) +update ddl_index_visibility set first_name='+dw', last_name='dw_rt' where id = 698; +--create index, indcheckxmin will be true +create index ddl_index_visibility_idx on ddl_index_visibility USING btree(id); +--explain, should be BitmapHeapScan +explain(costs off) select * from ddl_index_visibility where id=698; +select * from ddl_index_visibility where id=698; + +reset enable_seqscan; +DROP TABLE ddl_index_visibility;