您好,登錄后才能下訂單哦!
本節介紹排序的實現,排序的實現函數是ExecSort,與聚合函數類似,也有要一個初始化的過程ExecInitSort,本節主要介紹該函數的實現.
下面是測試SQL執行排序的計劃樹:
",,,,,"select bh,c1 from t_sort order by t_sort;",,,"psql"
2019-05-17 15:12:42.494 CST,"xdb","testdb",1519,"[local]",5cde5e9e.5ef,15,"SELECT",2019-05-17 15:11:26 CST,3/10,0,LOG,00000,"plan:"," {PLANNEDSTMT
:commandType 1
:queryId 0
:hasReturning false
:hasModifyingCTE false
:canSetTag true
:transientPlan false
:dependsOnRole false
:parallelModeNeeded false
:jitFlags 0
:planTree
{SORT
:startup_cost 14142.82
:total_cost 14392.82
:plan_rows 100000
:plan_width 66
:parallel_aware false
:parallel_safe true
:plan_node_id 0
:targetlist (...
)
:qual <>
:lefttree
{SEQSCAN
:startup_cost 0.00
:total_cost 1736.00
:plan_rows 100000
:plan_width 66
:parallel_aware false
:parallel_safe true
:plan_node_id 1
:targetlist (...
)
:qual <>
:lefttree <>
:righttree <>
:initPlan <>
:extParam (b)
:allParam (b)
:scanrelid 1
}
:righttree <>
:initPlan <>
:extParam (b)
:allParam (b)
:numCols 1
:sortColIdx 3
:sortOperators 2990
:collations 0
:nullsFirst false
}
:rtable (...
)
:resultRelations <>
:nonleafResultRelations <>
:rootResultRelations <>
:subplans <>
:rewindPlanIDs (b)
:rowMarks <>
:relationOids (o 278567)
:invalItems <>
:paramExecTypes <>
:utilityStmt <>
:stmt_location 0
:stmt_len 40
}
",,,,,"select bh,c1 from t_sort order by t_sort;",,,"psql"
SortState
排序運行期狀態信息
/* ----------------
* SortState information
* 排序運行期狀態信息
* ----------------
*/
typedef struct SortState
{
//基類
ScanState ss; /* its first field is NodeTag */
//是否需要隨機訪問排序輸出?
bool randomAccess; /* need random access to sort output? */
//結果集是否存在邊界?
bool bounded; /* is the result set bounded? */
//如存在邊界,需要多少個元組?
int64 bound; /* if bounded, how many tuples are needed */
//是否已完成排序?
bool sort_Done; /* sort completed yet? */
//是否使用有界值?
bool bounded_Done; /* value of bounded we did the sort with */
//使用的有界值?
int64 bound_Done; /* value of bound we did the sort with */
//tuplesort.c的私有狀態
void *tuplesortstate; /* private state of tuplesort.c */
//是否worker?
bool am_worker; /* are we a worker? */
//每個worker對應一個條目
SharedSortInfo *shared_info; /* one entry per worker */
} SortState;
/* ----------------
* Shared memory container for per-worker sort information
* per-worker排序信息的共享內存容器
* ----------------
*/
typedef struct SharedSortInfo
{
//worker個數?
int num_workers;
//排序機制
TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
} SharedSortInfo;
TuplesortInstrumentation
報告排序統計的數據結構.
/*
* Data structures for reporting sort statistics. Note that
* TuplesortInstrumentation can't contain any pointers because we
* sometimes put it in shared memory.
* 報告排序統計的數據結構.
* 注意TuplesortInstrumentation不能包含指針因為有時候會把該結構體放在共享內存中.
*/
typedef enum
{
SORT_TYPE_STILL_IN_PROGRESS = 0,//仍然在排序中
SORT_TYPE_TOP_N_HEAPSORT,//TOP N 堆排序
SORT_TYPE_QUICKSORT,//快速排序
SORT_TYPE_EXTERNAL_SORT,//外部排序
SORT_TYPE_EXTERNAL_MERGE//外部排序后的合并
} TuplesortMethod;//排序方法
typedef enum
{
SORT_SPACE_TYPE_DISK,//需要用上磁盤
SORT_SPACE_TYPE_MEMORY//使用內存
} TuplesortSpaceType;
typedef struct TuplesortInstrumentation
{
//使用的排序算法
TuplesortMethod sortMethod; /* sort algorithm used */
//排序使用空間類型
TuplesortSpaceType spaceType; /* type of space spaceUsed represents */
//空間消耗(以K為單位)
long spaceUsed; /* space consumption, in kB */
} TuplesortInstrumentation;
ExecInitSort為排序節點創建運行期信息并初始化outer子樹,邏輯較為簡單.
/* ----------------------------------------------------------------
* ExecInitSort
*
* Creates the run-time state information for the sort node
* produced by the planner and initializes its outer subtree.
* ----------------------------------------------------------------
*/
SortState *
ExecInitSort(Sort *node, EState *estate, int eflags)
{
SortState *sortstate;//排序運行期信息
SO1_printf("ExecInitSort: %s\n",
"initializing sort node");
/*
* create state structure
* 創建運行期狀態節點結構體
*/
sortstate = makeNode(SortState);
sortstate->ss.ps.plan = (Plan *) node;
sortstate->ss.ps.state = estate;
sortstate->ss.ps.ExecProcNode = ExecSort;
/*
* We must have random access to the sort output to do backward scan or
* mark/restore. We also prefer to materialize the sort output if we
* might be called on to rewind and replay it many times.
* 需要隨機訪問用于排序輸出用于執行后端搜索或者標記/存儲.
* 同時,如果可能在rewind或replay很多次的情況下,會傾向于物化排序輸出
*/
sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
EXEC_FLAG_BACKWARD |
EXEC_FLAG_MARK)) != 0;
sortstate->bounded = false;//結果集不存在邊界
sortstate->sort_Done = false;//未完成排序
sortstate->tuplesortstate = NULL;//元組排序狀態為NULL
/*
* Miscellaneous initialization
* 執行各種初始化
*
* Sort nodes don't initialize their ExprContexts because they never call
* ExecQual or ExecProject.
* 排序節點不需要初始化ExprContexts,因為排序不會調用ExecQual/ExecProject
*/
/*
* initialize child nodes
* 初始化子節點
*
* We shield the child node from the need to support REWIND, BACKWARD, or
* MARK/RESTORE.
* 子節點不需要支持REWIND, BACKWARD, MARK/RESTORE
*/
eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
//外(左)子節點往往是掃描節點,如SeqScan等
outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
* Initialize scan slot and type.
* 初始化掃描slot和類型
*/
ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss);
/*
* Initialize return slot and type. No need to initialize projection info
* because this node doesn't do projections.
* 初始化返回slot和類型.
* 不需要初始化投影信息因為排序節點不需要投影.
*/
ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n",
"sort node initialized");
return sortstate;
}
/* ----------------
* ExecCreateSlotFromOuterPlan
* ----------------
*/
void
ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
{
PlanState *outerPlan;
TupleDesc tupDesc;
outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetResultType(outerPlan);
ExecInitScanTupleSlot(estate, scanstate, tupDesc);
}
/* ----------------
* ExecInitScanTupleSlot
* ----------------
*/
void
ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
{
scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
tupledesc);
scanstate->ps.scandesc = tupledesc;
}
N/A
N/A
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。