文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL 源码解读(192)- 查询#108(排序#1 - ExecInitSort)

2024-04-02 19:55

关注

本节介绍排序的实现,排序的实现函数是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
排序运行期状态信息




typedef struct SortState
{
    //基类
    ScanState    ss;                
    //是否需要随机访问排序输出?
    bool        randomAccess;    
    //结果集是否存在边界?
    bool        bounded;        
    //如存在边界,需要多少个元组?
    int64        bound;            
    //是否已完成排序?
    bool        sort_Done;        
    //是否使用有界值?
    bool        bounded_Done;    
    //使用的有界值?
    int64        bound_Done;        
    //tuplesort.c的私有状态
    void       *tuplesortstate; 
    //是否worker?
    bool        am_worker;        
    //每个worker对应一个条目
    SharedSortInfo *shared_info;    
} SortState;

typedef struct SharedSortInfo
{
    //worker个数?
    int            num_workers;
    //排序机制
    TuplesortInstrumentation sinstrument[FLEXIBLE_ARRAY_MEMBER];
} SharedSortInfo;

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; 
    //排序使用空间类型
    TuplesortSpaceType spaceType;    
    //空间消耗(以K为单位)
    long        spaceUsed;        
} TuplesortInstrumentation;

二、源码解读

ExecInitSort为排序节点创建运行期信息并初始化outer子树,逻辑较为简单.




SortState *
ExecInitSort(Sort *node, EState *estate, int eflags)
{
    SortState  *sortstate;//排序运行期信息
    SO1_printf("ExecInitSort: %s\n",
               "initializing sort node");
    
    sortstate = makeNode(SortState);
    sortstate->ss.ps.plan = (Plan *) node;
    sortstate->ss.ps.state = estate;
    sortstate->ss.ps.ExecProcNode = ExecSort;
    
    sortstate->randomAccess = (eflags & (EXEC_FLAG_REWIND |
                                         EXEC_FLAG_BACKWARD |
                                         EXEC_FLAG_MARK)) != 0;
    sortstate->bounded = false;//结果集不存在边界
    sortstate->sort_Done = false;//未完成排序
    sortstate->tuplesortstate = NULL;//元组排序状态为NULL
    
    
    eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
    //外(左)子节点往往是扫描节点,如SeqScan等
    outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate, eflags);
    
    ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss);
    
    ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
    sortstate->ss.ps.ps_ProjInfo = NULL;
    SO1_printf("ExecInitSort: %s\n",
               "sort node initialized");
    return sortstate;
}

void
ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
{
    PlanState  *outerPlan;
    TupleDesc    tupDesc;
    outerPlan = outerPlanState(scanstate);
    tupDesc = ExecGetResultType(outerPlan);
    ExecInitScanTupleSlot(estate, scanstate, tupDesc);
}

void
ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
{
    scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
                                                     tupledesc);
    scanstate->ps.scandesc = tupledesc;
}

三、跟踪分析

N/A

四、参考资料

N/A

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯