with as +分析函数优化自链接

本文探讨了如何使用with as子查询优化自链接查询。通过对比原查询和改写后的查询计划,展示了with as子查询在窗口函数的帮助下,如何更高效地找出每个Bus_Code的最小Para_Id。

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

select para_id
  from dwf.f_Savc_Buscode b
 where b.Para_Id = (SELECT MIN(Para_Id)
                      FROM Dwf.f_Savc_Buscode
                     WHERE Bus_Code = b.Bus_Code);

SQL> set linesize 200
SQL> set pagesize 200
SQL> explain plan for select para_id
  from dwf.f_Savc_Buscode b
 where b.Para_Id = (SELECT MIN(Para_Id)
                      FROM Dwf.f_Savc_Buscode
                     WHERE Bus_Code = b.Bus_Code);  2    3    4    5  

Explained.

SQL> select * from table(dbms_xplan.display());

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1952012934
<think>我们正在讨论如何使用draw.io来绘制C++函数调用关系图。根据引用内容,我们得知C++本身不直接支持图形绘制,但可以通过第三方库实现。然而,这里我们关注的是如何利用draw.io(一个在线图表绘制工具)来绘制函数调用关系图,而不是在C++程序中绘制图形。函数调用关系图(CallGraph)用于表示程序中函数之间的调用关系。在C++中,我们可以通过一些工具生成函数调用关系数据,然后将这些数据导入到draw.io中绘制图表。步骤:1.生成C++项目的函数调用关系数据。我们可以使用一些静态分析工具,如Doxygen、CppDepend、Understand或Clang的插件,来生成函数调用关系。例如,Doxygen可以生成调用关系图,但通常是以图片形式,我们需要提取结构化的数据(如调用对)来在draw.io中绘制。2.将函数调用关系数据转换为draw.io可接受的格式。draw.io支持多种导入方式,但通常我们手动绘制或者通过CSV等格式导入节点和边。我们可以将函数作为节点,调用关系作为有向边。3.在draw.io中绘制图表。由于draw.io没有直接导入C++调用关系图的功能,我们需要手动或通过脚本转换数据后,使用draw.io的图形化界面进行绘制。详细步骤:第一步:使用工具生成调用关系数据-使用Doxygen:配置Doxygen生成调用关系图(需要设置CALL_GRAPH和CALLER_GRAPH为YES),但Doxygen生成的图是图片格式,我们无法直接导入draw.io。因此,我们可以考虑使用其他工具。-使用Clang:Clang有自带的工具可以生成调用关系。例如,使用`clang-S-emit-llvm-oout.ll`生成LLVMIR,然后使用`opt-analyze-dot-callgraphout.ll`生成一个callgraph.dot文件(DOT格式)。-使用CppDepend:它可以生成依赖关系,并导出为XML或CSV格式。第二步:转换数据-如果我们得到的是DOT格式(Graphviz格式),我们可以使用在线工具将DOT文件转换为draw.io支持的格式(如CSV),或者直接导入到draw.io(draw.io支持导入DOT文件)。第三步:在draw.io中绘制-方法1:直接导入DOT文件打开draw.io->文件->导入->选择DOT文件。-方法2:手动绘制(适用于小项目)在draw.io中,我们可以使用“流程图”形状来绘制函数节点,使用箭头表示调用关系。示例:手动绘制步骤1.打开draw.io(https://app.diagrams.net/)2.选择创建新图表,选择“流程图”模板。3.从左侧形状库中拖拽“矩形”作为函数节点,在节点内填写函数名。4.使用箭头连接调用者函数和被调用函数(箭头从调用者指向被调用者)。5.可以调整布局,使用自动布局功能(在“排列”菜单中)。如果项目较大,建议使用工具生成DOT文件然后导入。注意事项:-静态分析工具可能无法完全反映运行时调用关系(比如虚函数调用、函数指针等),因此静态调用图可能不完整。-对于大型项目,生成的调用图可能非常复杂,需要简化(例如只关注特定模块)。参考引用:[^1]提到C++可以通过第三方库实现图形绘制,但这里我们使用外部工具(draw.io)来绘制调用图,与引用中提到的库无关。[^2]中提到的书籍和资源可以帮助理解C++的内部机制,但生成调用关系图不需要深入编译器知识。因此,推荐使用Clang生成DOT格式的调用图,然后导入draw.io。具体操作步骤:1.安装LLVM(包含Clang和opt工具)。2.将C++源文件编译为LLVMIR(如果项目有多个文件,需要先编译成单个IR文件,或者为每个文件生成然后合并?注意:调用关系图需要整个项目,所以最好使用链接后的整个程序IR,但通常静态分析是针对单个文件。因此,对于多文件项目,需要分别生成然后合并?或者使用其他工具如scan-build?)实际上,对于多文件,我们可以使用编译命令数据库(compile_commands.json)和工具如`clang-extdef-mapping`或`clang-check`来生成整个项目的调用关系。3.生成DOT文件:例如,对于单个文件:clang++-S-emit-llvm-oout.llmain.cppopt-disable-output-dot-callgraphout.ll#这会生成callgraph.dot4.打开draw.io,选择“文件”->“导入”->“从...”,然后选择“DOT”文件格式,导入callgraph.dot。如果项目复杂,生成的图可能非常大,导入后可能需要使用自动布局功能来调整。替代方案:使用Doxygen生成调用关系图,然后导出为DOT(在Doxygen配置中设置:HAVE_DOT=YES,CALL_GRAPH=YES,CALLER_GRAPH=YES,EXTRACT_ALL=YES),然后使用Doxygen生成的DOT文件导入到draw.io。总结:-对于简单项目,手动绘制即可。-对于复杂项目,建议使用Clang或Doxygen生成DOT文件,然后导入draw.io。相关问题:1.如何安装Clang并生成LLVMIR?2.如何使用Doxygen生成C++项目的调用关系图?3.在draw.io中如何调整大型调用关系图的布局?4.除了静态调用图,如何获取动态(运行时)函数调用关系?5.如何简化大型项目的调用关系图?</think>### 如何使用 draw.io 绘制 C++ 函数调用关系图 #### **核心步骤** 1. **生成调用关系数据** 使用工具解析 C++ 代码生成结构化调用关系数据: ```bash # 使用 Doxygen 生成 XML 调用关系数据 doxygen -x Doxyfile ``` 配置 Doxyfile 关键参数: ```ini EXTRACT_ALL = YES CALL_GRAPH = YES CALLER_GRAPH = YES GENERATE_XML = YES ``` 2. **转换数据为 draw.io 兼容格式** 将 XML 转换为 CSV 格式(示例 Python 脚本): ```python import xml.etree.ElementTree as ET tree = ET.parse('call_graph.xml') root = tree.getroot() with open('calls.csv', 'w') as f: f.write("Source,Target\n") # CSV 表头 for caller in root.findall('.//function'): caller_name = caller.get('name') for callee in caller.findall('.//calledby'): f.write(f"{caller_name},{callee.get('name')}\n") ``` 3. **在 draw.io 中绘制** - **导入 CSV**: 打开 draw.io → `文件` → `导入` → `CSV` → 选择生成的 `calls.csv` [自动生成节点和箭头] - **手动优化**: - 使用 `布局` → `自动排版` 调整拓扑结构 - 用`容器形状`分组相关模块(如类或命名空间) - 关键函数用颜色标记(如红色表示核心函数) ![draw.io 界面示例](https://www.drawio.com/doc/faq/import-csv-data.png) *(图:draw.io 的 CSV 导入界面示意图)* #### **高级技巧** - **动态调用分析**: 结合 `gprof` 生成运行时调用数据: ```bash g++ -pg myapp.cpp -o myapp ./myapp gprof myapp gmon.out > callgraph.txt ``` - **第三方工具整合**: - **CppDepend**:直接导出交互式调用图(支持 PNG/SVG) - **Understand Scitools**:生成带权重的调用关系(可过滤低频调用) - **draw.io 专属优化**: - 使用 `图层` 功能分离不同抽象层级(如 API 层/底层实现) - 通过 `样式刷` 统一节点风格 - 添加 `文本注释` 说明调用条件(如虚函数重载) #### **注意事项** 1. **静态分析的局限性** 无法捕获通过函数指针或虚表的动态调用(需结合运行时分析)[^2]。 2. **大型项目优化** - 在 CSV 生成阶段过滤工具函数(如 `std::` 开头的调用) - 使用 draw.io 的 `折叠容器` 隐藏次要模块 3. **版本控制整合** 将 draw.io 文件保存为 `.xml` 格式纳入 Git,便于追踪调用关系变更 > **案例**:Android 系统开发中常用此类方法分析 SurfaceFlinger 服务的调用链路,快速定位渲染流程中的瓶颈[^4]。 --- ### **相关问题** 1. 如何避免大型 C++ 项目调用关系图过于复杂? 2. 哪些工具可以捕获运行时动态函数调用关系? 3. 如何将 draw.io 生成的调用图嵌入技术文档? 4. 除了函数调用,draw.io 还能分析哪些代码结构关系? 5. 如何通过调用关系图识别循环依赖问题? [^1]: C++图形编程需依赖第三方库,但调用关系分析属于静态代码分析范畴 [^2]: 编译器优化可能影响调用关系可见性,需关闭优化选项(如 `-O0`) [^3]: 模板函数实例化会在调用图中显示为独立节点 [^4]: 系统服务如 SurfaceFlinger 的调用链分析对性能优化至关重要
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scan724

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值