diff --git a/src/common/backend/nodes/copyfuncs.cpp b/src/common/backend/nodes/copyfuncs.cpp index 2d070172a..1f183924a 100644 --- a/src/common/backend/nodes/copyfuncs.cpp +++ b/src/common/backend/nodes/copyfuncs.cpp @@ -539,6 +539,7 @@ static void CopyScanFields(const Scan* from, Scan* newnode) /* copy remainder of node.*/ COPY_NODE_FIELD(tablesample); CopyMemInfoFields(&from->mem_info, &newnode->mem_info); + COPY_SCALAR_FIELD(executeBatch); } /* diff --git a/src/gausskernel/optimizer/plan/createplan.cpp b/src/gausskernel/optimizer/plan/createplan.cpp index 7b4025bd0..2cf80135b 100644 --- a/src/gausskernel/optimizer/plan/createplan.cpp +++ b/src/gausskernel/optimizer/plan/createplan.cpp @@ -5497,6 +5497,7 @@ static SeqScan* make_seqscan(List* qptlist, List* qpqual, Index scanrelid) plan->righttree = NULL; plan->isDeltaTable = false; node->scanrelid = scanrelid; + node->executeBatch = false; return node; } diff --git a/src/gausskernel/optimizer/plan/planner.cpp b/src/gausskernel/optimizer/plan/planner.cpp index ab85ed5ca..a6c354adf 100644 --- a/src/gausskernel/optimizer/plan/planner.cpp +++ b/src/gausskernel/optimizer/plan/planner.cpp @@ -8209,6 +8209,27 @@ static bool has_column_store_relation(Plan* top_plan) } } break; + case T_IndexScan: + case T_SeqScan: { + if (u_sess->attr.attr_sql.enable_force_vector_engine) { + ListCell* cell = NULL; + TargetEntry* entry = NULL; + Var* var = NULL; + foreach (cell, top_plan->targetlist) { + entry = (TargetEntry*)lfirst(cell); + if (IsA(entry->expr, Var)) { + var = (Var*)entry->expr; + if (var->varattno > 0 && var->varoattno > 0 && + !IsTypeSupportedByCStore(var->vartype, var->vartypmod)) { + return false; + } + } + } + return true; + } + return false; + } break; + default: if (outerPlan(top_plan)) { if (has_column_store_relation(outerPlan(top_plan))) @@ -8475,6 +8496,22 @@ static bool vector_engine_walker(Plan* result_plan, bool check_rescan) return false; } case T_IndexScan: + if (u_sess->attr.attr_sql.enable_force_vector_engine) { + ListCell* cell = NULL; + TargetEntry* entry = NULL; + Var* var = NULL; + foreach (cell, result_plan->targetlist) { + entry = (TargetEntry*)lfirst(cell); + if (IsA(entry->expr, Var)) { + var = (Var*)entry->expr; + if (var->varattno > 0 && var->varoattno > 0 && + !IsTypeSupportedByCStore(var->vartype, var->vartypmod)) { + return true; + } + } + } + return false; + } case T_IndexOnlyScan: case T_BitmapHeapScan: case T_TidScan: @@ -8812,6 +8849,11 @@ static Plan* fallback_plan(Plan* result_plan) } } break; + case T_SeqScan: { + ((SeqScan*)result_plan)->executeBatch = false; + result_plan->vec_output = false; + } break; + default: break; } @@ -8877,7 +8919,14 @@ Plan* vectorize_plan(Plan* result_plan, bool ignore_remotequery) break; } case T_SeqScan: { - if (result_plan->isDeltaTable) { + if (result_plan->isDeltaTable || u_sess->attr.attr_sql.enable_force_vector_engine) { + ((SeqScan*)result_plan)->executeBatch = true; + result_plan->vec_output = true; + } + break; + } + case T_IndexScan: { + if (u_sess->attr.attr_sql.enable_force_vector_engine) { result_plan = (Plan*)make_rowtovec(result_plan); } break; diff --git a/src/gausskernel/runtime/executor/execScan.cpp b/src/gausskernel/runtime/executor/execScan.cpp index fefade4a2..18876bef1 100644 --- a/src/gausskernel/runtime/executor/execScan.cpp +++ b/src/gausskernel/runtime/executor/execScan.cpp @@ -23,6 +23,8 @@ #include "executor/executor.h" #include "miscadmin.h" #include "utils/memutils.h" +#include "vecexecutor/vecexecutor.h" +#include "vecexecutor/vecnoderowtovector.h" /* * ExecScanFetch -- fetch next potential tuple @@ -379,3 +381,45 @@ void ExecScanReScan(ScanState* node) estate->es_epqScanDone[scan_rel_id - 1] = false; } } + +VectorBatch* ExecBatchScan(ScanState* node, ExecScanAccessMtd access_mtd, + ExecScanRecheckMtd recheck_mtd) +{ + VectorBatch* p_out_batch = node->m_pCurrentBatch; + + ExprContext* econtext = node->ps.ps_ExprContext; + TupleTableSlot* result_slot = NULL; + + ResetExprContext(econtext); + /* + * We don't go through the regular ExecScan interface as we will handle all + * common code ourselves here + */ + p_out_batch->Reset(true); + + if (node->is_scan_end) { + return p_out_batch; + } + + for (;;) { + result_slot = ExecScan(node, access_mtd, recheck_mtd); + if (TupIsNull(result_slot)) { + node->is_scan_end = true; + break; + } + + if (VectorizeOneTuple(p_out_batch, result_slot, econtext->ecxt_per_tuple_memory)) { + /* It is full now, now return current batch */ + break; + } + } + + p_out_batch->FixRowCount(); + + /* Response to the stop query flag. */ + if (unlikely(executorEarlyStop())) + return NULL; + + return p_out_batch; +} + diff --git a/src/gausskernel/runtime/executor/nodeSeqscan.cpp b/src/gausskernel/runtime/executor/nodeSeqscan.cpp index 19c32b064..bd17e5d6c 100644 --- a/src/gausskernel/runtime/executor/nodeSeqscan.cpp +++ b/src/gausskernel/runtime/executor/nodeSeqscan.cpp @@ -40,6 +40,7 @@ #include "nodes/execnodes.h" #include "nodes/makefuncs.h" #include "optimizer/pruning.h" +#include "vecexecutor/vecexecutor.h" extern void StrategyGetRingPrefetchQuantityAndTrigger(BufferAccessStrategy strategy, int* quantity, int* trigger); /* ---------------------------------------------------------------- @@ -254,6 +255,11 @@ TupleTableSlot* ExecSeqScan(SeqScanState* node) return ExecScan((ScanState*)node, node->ScanNextMtd, (ExecScanRecheckMtd)SeqRecheck); } +VectorBatch* ExecBatchSeqScan(SeqScanState* node) +{ + return ExecBatchScan((ScanState*)node, node->ScanNextMtd, (ExecScanRecheckMtd)SeqRecheck); +} + /* ---------------------------------------------------------------- * SeqScan_Pref_Quantity * @@ -541,6 +547,17 @@ SeqScanState* ExecInitSeqScan(SeqScan* node, EState* estate, int eflags) ExecAssignScanProjectionInfo(scanstate); + if (node->executeBatch) { + /* + * Init result batch and work batch. Work batch has to contain all columns as qual is + * running against it. we shall avoid with this after we fix projection elimination. + */ + scanstate->m_pCurrentBatch = New(CurrentMemoryContext) + VectorBatch(CurrentMemoryContext, scanstate->ps.ps_ResultTupleSlot->tts_tupleDescriptor); + + scanstate->ps.vectorized = true; + } + return scanstate; } @@ -640,6 +657,13 @@ void ExecReScanSeqScan(SeqScanState* node) ExecScanReScan((ScanState*)node); } +void ExecReScanBatchSeqScan(SeqScanState* node) +{ + node->is_scan_end = false; + node->m_pCurrentBatch->m_rows = 0; + ExecReScan(&(node->ps)); +} + /* ---------------------------------------------------------------- * ExecSeqMarkPos(node) * diff --git a/src/gausskernel/runtime/vecexecutor/vecexecutor.cpp b/src/gausskernel/runtime/vecexecutor/vecexecutor.cpp index 732e246f9..9f705aca6 100644 --- a/src/gausskernel/runtime/vecexecutor/vecexecutor.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecexecutor.cpp @@ -115,6 +115,7 @@ VectorEngineFunc VectorEngineRunner[] = { reinterpret_cast(ExecVecMaterial), reinterpret_cast(ExecVecMergeJoin), reinterpret_cast(ExecVecWindowAgg), + reinterpret_cast(ExecBatchSeqScan), }; FORCE_INLINE diff --git a/src/gausskernel/runtime/vecexecutor/vecnode/vecrescan.cpp b/src/gausskernel/runtime/vecexecutor/vecnode/vecrescan.cpp index f53a21062..461e71669 100644 --- a/src/gausskernel/runtime/vecexecutor/vecnode/vecrescan.cpp +++ b/src/gausskernel/runtime/vecexecutor/vecnode/vecrescan.cpp @@ -32,6 +32,7 @@ #include "storage/cstore/cstore_compress.h" #include "access/cstore_am.h" #include "executor/nodeModifyTable.h" +#include "executor/nodeSeqscan.h" #include "vecexecutor/vecnoderowtovector.h" #include "vecexecutor/vecnestloop.h" #include "vecexecutor/vecmaterial.h" @@ -220,6 +221,9 @@ void VecExecReScan(PlanState* node) case T_VecWindowAggState: ExecReScanVecWindowAgg((VecWindowAggState*)node); break; + case T_SeqScanState: + ExecReScanBatchSeqScan((SeqScanState*)node); + break; default: ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 0429327c2..1685e06c2 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -318,6 +318,8 @@ extern ExprContext* CreateExprContext(EState* estate); extern ExprContext* CreateStandaloneExprContext(void); extern void FreeExprContext(ExprContext* econtext, bool isCommit); extern void ReScanExprContext(ExprContext* econtext); +extern VectorBatch* ExecBatchScan(ScanState* node, ExecScanAccessMtd access_mtd, ExecScanRecheckMtd recheck_mtd); +extern VectorBatch* ExecBatchSeqScan(SeqScanState* node); #define ResetExprContext(econtext) MemoryContextReset((econtext)->ecxt_per_tuple_memory) diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h index dc6f5f81d..8822384ef 100644 --- a/src/include/executor/nodeSeqscan.h +++ b/src/include/executor/nodeSeqscan.h @@ -22,6 +22,7 @@ extern void ExecEndSeqScan(SeqScanState* node); extern void ExecSeqMarkPos(SeqScanState* node); extern void ExecSeqRestrPos(SeqScanState* node); extern void ExecReScanSeqScan(SeqScanState* node); +extern void ExecReScanBatchSeqScan(SeqScanState* node); extern void InitScanRelation(SeqScanState* node, EState* estate); #endif /* NODESEQSCAN_H */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index a70cc41ce..e494ecd71 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1553,6 +1553,9 @@ typedef struct ScanState { bool isSampleScan; /* identify is it table sample scan or not. */ SampleScanParams sampleScanInfo; /* TABLESAMPLE params include type/seed/repeatable. */ ExecScanAccessMtd ScanNextMtd; + + VectorBatch* m_pScanBatch; // batch to work on + VectorBatch* m_pCurrentBatch; // output batch } ScanState; /* diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index a80d8fb32..68995b2fd 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -147,8 +147,6 @@ typedef enum NodeTag { T_BitmapAndState, T_BitmapOrState, T_ScanState, - T_SeqScanState, - T_IndexScanState, T_IndexOnlyScanState, T_BitmapIndexScanState, T_BitmapHeapScanState, @@ -663,6 +661,8 @@ typedef enum NodeTag { T_VecMaterialState, T_VecMergeJoinState, T_VecWindowAggState, + T_SeqScanState, + T_IndexScanState, // this must put last for vector engine runtime state T_VecEndState, diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 01c9856e6..7412af285 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -542,8 +542,11 @@ typedef struct Scan { /* use struct pointer to avoid including parsenodes.h here */ TableSampleClause* tablesample; - /* Memory info for scan node, now it just used on indexscan, indexonlyscan, bitmapscan, dfsindexscan */ + /* Memory info for scan node, now it just used on indexscan, indexonlyscan, bitmapscan, dfsindexscan */ OpMemInfo mem_info; + + /* use vector engine to execute this scan */ + bool executeBatch; } Scan; /* ----------------