@ -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);
|
||||
|
@ -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 <bool is_dml, bool isonlyindex> 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 <bool is_dml, bool isonlyindex> 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) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user