广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL 源码解读(192)- 查询#108(排序#1 - ExecInitSort)
  • 546
分享到

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

2024-04-02 19:04:59 546人浏览 安东尼
摘要

本节介绍排序的实现,排序的实现函

本节介绍排序的实现,排序的实现函数是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

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL 源码解读(192)- 查询#108(排序#1 - ExecInitSort)

本文链接: https://www.lsjlt.com/news/48719.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作