用二叉树的后序遍历来看oracle执行计划的执行顺序

本文通过实例讲解如何利用二叉树的后序遍历理解Oracle执行计划的执行顺序。借助v$sql_plan视图,将执行计划转化为二叉树,并展示从左孩子开始的后序遍历过程,揭示SQL执行的正确顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    我们先用一个小表来,来说明一下,oracle执行计划该注意哪些地方。

hr@ORCL> set autotrace traceonly
hr@ORCL> select * from t;

模糊比较两条sql的优劣时,建议先查看以下两个值:
Cost (%CPU):cpu代价,这个值要代数和。比如,这里是3+3=6
consistent gets:这个值一般要多执行几次!让他稳定下来,才有比较的意义。
Execution Plan :
----------------------------------------------------------
Plan hash value: 1601196873
下面这个计划看的方法:由里到外,由上到下
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    |     1 |     6 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------


Statistics
----------------------------------------------------------
        228  recursive calls  --访问数据字典得到元数据。第二次执行相同语句,递归调用基本为零。
在完全二叉树的情况下,如果给定其后序历结果,我们可以通过一定的推导规则还原出层序历的结果。 ### 原理分析 1. **后序历的特点** 后序历的顺序是“左子树 -> 右子树 -> 根节点”。对于一棵完全二叉树来说,根节点总是出现在序列的最后一个位置。 2. **完全二叉树的特性** 完全二叉树的一个重要性质是,除了最后一层外,其他所有层都是满的,并且最后一层的节点从左到右连续排列。这一特点使得我们可以利用数学公式来定位每个节点的位置。 3. **推导过程** - 找到后序历中的最后一个元素,即为整棵树的根节点。 - 确定了根节点之后,可以根据左右子树的大小划分剩下的部分(注意:由于它是完全二叉树,因此可以精确计算左右子树包含多少个节点)。 - 对于每一个子树递归地应用上述步骤,直到处理完所有的节点为止。 - 最终将得到的所有根按层次插入到数组中形成层序历。 下面给出基于以上思路的具体C++实现: ```cpp #include <iostream> #include <vector> using namespace std; // 辅助函数用于找到某个范围内的根并返回其索引 int findRoot(const vector<int>& postorder, int start, int end) { if (start > end) return -1; // 当前区间的最后一个是该区间对应的根结点 return end; } void constructLevelOrder(vector<int>& levelOrderResult, const vector<int>& postorder, int lStart, int lEnd, int rSize){ if(lStart > lEnd || rSize <0 ) return ; int rootIndex = findRoot(postorder,lStart,lEnd); // 添加当前根节点进入level order 结果集里 levelOrderResult.push_back(postorder[rootIndex]); // 左右孩子的长度计算依据完全二叉树属性得出 int leftChildRangeLength=(rSize*2 +1 <=lEnd-lStart)?(rSize*2):((lEnd-lStart)/2); // 处理左边的部分 constructLevelOrder(levelOrderResult,postorder,lStart,rootIndex-leftChildRangeLength-1,rSize/2); // 再处理右边部分 constructLevelOrder(levelOrderResult,postorder,rootIndex-rSize+1,rootIndex-1,(rSize-1)/2); } vector<int> postTo
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值