!511 修复索引可见性问题

Merge pull request !511 from TotaJ/bugfix/parallel_cost
This commit is contained in:
opengauss-bot
2020-12-21 14:34:16 +08:00
committed by Gitee
6 changed files with 90 additions and 17 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;