当前位置: 首页 > article >正文

PostgreSQL 13.8 子查询优化实战:手把手教你读懂 `pull_up_sublinks` 源码

PostgreSQL 13.8 子查询优化实战手把手教你读懂pull_up_sublinks源码数据库查询优化器是数据库系统的核心组件之一它负责将用户提交的SQL语句转换为高效的执行计划。在PostgreSQL中子查询优化是查询优化的重要环节而pull_up_sublinks则是处理WHERE子句中子查询子链接的关键函数。本文将带您深入PostgreSQL 13.8源码从实战角度解析这一优化过程。1. 环境准备与源码定位要深入理解pull_up_sublinks的工作原理首先需要搭建一个适合的调试环境。以下是推荐的开发环境配置操作系统Linux推荐Ubuntu 20.04 LTSPostgreSQL版本13.8源码调试工具GDB 10.1编译选项./configure --enable-debug关键源码文件位于src/backend/optimizer/prep/prepjointree.c中。我们可以通过以下步骤快速定位到目标函数# 在PostgreSQL源码目录中 grep -rn pull_up_sublinks src/backend/在GDB中设置断点的命令示例break pull_up_sublinks_jointree_recurse break pull_up_sublinks_qual_recurse2. 子链接优化的核心数据结构理解PostgreSQL中的关键数据结构是分析优化器行为的基础。以下是pull_up_sublinks处理过程中涉及的主要数据结构数据结构描述关键字段PlannerInfo查询规划上下文parse查询树、simple_rel_array基本关系数组Query查询树表示jointreeFROM/WHERE子句、targetListSELECT列表FromExprFROM子句节点fromlistFROM列表、qualsWHERE条件JoinExprJOIN表达式jointype连接类型、larg/rarg左右参数RangeTblRef范围表引用rtindex范围表索引SubLink子链接表达式subLinkType子链接类型、testexpr测试表达式这些数据结构共同构成了查询优化器处理子链接的基础框架。特别值得注意的是SubLink类型它定义了PostgreSQL支持的子链接类型typedef enum SubLinkType { EXISTS_SUBLINK, ALL_SUBLINK, ANY_SUBLINK, ROWCOMPARE_SUBLINK, EXPR_SUBLINK, MULTIEXPR_SUBLINK, ARRAY_SUBLINK, CTE_SUBLINK } SubLinkType;3. 子链接上拉的递归处理流程pull_up_sublinks的核心是一个递归处理过程主要包含两个关键函数pull_up_sublinks_jointree_recurse处理FROM子句中的连接树pull_up_sublinks_qual_recurse处理WHERE子句中的条件表达式以下是pull_up_sublinks_jointree_recurse的简化处理逻辑static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids) { if (jtnode NULL) { *relids NULL; } else if (IsA(jtnode, RangeTblRef)) { // 处理基础表引用 int varno ((RangeTblRef *) jtnode)-rtindex; *relids bms_make_singleton(varno); } else if (IsA(jtnode, FromExpr)) { // 处理FROM表达式 FromExpr *f (FromExpr *) jtnode; // 递归处理FROM列表 foreach(l, f-fromlist) { newchild pull_up_sublinks_jointree_recurse(root, lfirst(l), childrelids); newfromlist lappend(newfromlist, newchild); } // 处理WHERE条件 newf-quals pull_up_sublinks_qual_recurse(root, f-quals, jtlink, frelids, NULL, NULL); } else if (IsA(jtnode, JoinExpr)) { // 处理JOIN表达式 JoinExpr *j (JoinExpr *) jtnode; // 递归处理左右子树 j-larg pull_up_sublinks_jointree_recurse(root, j-larg, leftrelids); j-rarg pull_up_sublinks_jointree_recurse(root, j-rarg, rightrelids); // 根据连接类型处理连接条件 switch (j-jointype) { case JOIN_INNER: j-quals pull_up_sublinks_qual_recurse(root, j-quals, jtlink, bms_union(leftrelids, rightrelids), NULL, NULL); break; case JOIN_LEFT: j-quals pull_up_sublinks_qual_recurse(root, j-quals, j-rarg, rightrelids, NULL, NULL); break; // 其他连接类型处理... } } return jtnode; }4. 不同类型子链接的转换策略PostgreSQL对不同类型的子链接采用不同的转换策略主要通过pull_up_sublinks_qual_recurse函数实现4.1 ANY子链接的转换ANY子链接包括IN、SOME等会被转换为半连接SEMI JOIN。转换过程由convert_ANY_sublink_to_join函数完成JoinExpr * convert_ANY_sublink_to_join(PlannerInfo *root, SubLink *sublink, Relids available_rels) { // 检查子查询是否引用外层变量 if (contain_vars_of_level((Node *) subselect, 1)) return NULL; // 创建新的RangeTblEntry nsitem addRangeTableEntryForSubquery(pstate, subselect, makeAlias(ANY_subquery, NIL), false, false); // 构建JoinExpr result makeNode(JoinExpr); result-jointype JOIN_SEMI; result-rarg (Node *) rtr; // 子查询作为右参数 result-quals convert_testexpr(root, sublink-testexpr, subquery_vars); return result; }4.2 EXISTS子链接的转换EXISTS子链接同样会被转换为半连接而NOT EXISTS则会被转换为反连接ANTI JOIN。这是通过convert_EXISTS_sublink_to_join函数实现的JoinExpr * convert_EXISTS_sublink_to_join(PlannerInfo *root, SubLink *sublink, bool under_not, Relids available_rels) { // 简化EXISTS查询 if (!simplify_EXISTS_query(root, subselect)) return NULL; // 提取WHERE条件 whereClause subselect-jointree-quals; // 构建JoinExpr result makeNode(JoinExpr); result-jointype under_not ? JOIN_ANTI : JOIN_SEMI; // 直接使用子查询中的FROM列表 if (list_length(subselect-jointree-fromlist) 1) result-rarg (Node *) linitial(subselect-jointree-fromlist); else result-rarg (Node *) subselect-jointree; result-quals whereClause; return result; }5. 实战调试技巧与案例分析要真正理解子链接优化的过程最好的方法是通过实际案例进行调试分析。以下是一个典型的调试流程准备测试SQLEXPLAIN SELECT * FROM orders o WHERE EXISTS (SELECT 1 FROM customers c WHERE c.id o.customer_id AND c.status active);设置断点break pull_up_sublinks break pull_up_sublinks_jointree_recurse break convert_EXISTS_sublink_to_join关键调试观察点subselect-jointree-quals的变化available_rels的传递过程生成的JoinExpr结构在调试过程中可以重点关注以下变量root-parse-jointree查询的FROM/WHERE结构sublink-subLinkType子链接类型j-jointype生成的连接类型通过实际跟踪这些数据结构的变换过程可以深入理解PostgreSQL如何将子查询转换为更高效的连接操作。

相关文章:

PostgreSQL 13.8 子查询优化实战:手把手教你读懂 `pull_up_sublinks` 源码

PostgreSQL 13.8 子查询优化实战:手把手教你读懂 pull_up_sublinks 源码 数据库查询优化器是数据库系统的核心组件之一,它负责将用户提交的SQL语句转换为高效的执行计划。在PostgreSQL中,子查询优化是查询优化的重要环节,而pull_u…...

C语言变量与运算符详解:从内存管理到高效编程实践

1. 从零到一:为什么C语言是程序员的“内功心法”?如果你刚看完系列的第一篇,对C语言有了一个模糊的印象,觉得它古老、复杂,甚至有点“过时”,那太正常了。我刚开始接触编程时,也这么想。为什么放…...

OpenClaw 中最经典的 6 款skill,真正能进工作流的 skills

2026 开年至今,AI 圈里两个词出镜率最高:龙虾 和 Skill。 龙虾更像一阵风——话题来得快,讨论散得也快;Skill 却在慢慢变成能天天用的东西:装一次,反复省时间。 可惜市面上不少 Skill 推荐文不太耐看&…...

手把手教你用STM32实现国标交流充电桩的CP信号检测(附完整代码)

手把手教你用STM32实现国标交流充电桩的CP信号检测(附完整代码) 在电动汽车充电基础设施快速发展的今天,交流充电桩因其成本优势和广泛适用性成为市场主流。作为嵌入式开发者,理解并实现充电控制导引(CP)信…...

体验 Taotoken 官方价折扣活动对个人开发者月度支出的实际影响

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 体验 Taotoken 官方价折扣活动对个人开发者月度支出的实际影响 作为一名独立开发者,我日常需要调用多种大模型 API 来完…...

【JPCS出版、EI检索稳定】2026年航空航天工程与空天信息国际学术会议(ICAEAI 2026)

2026年航空航天工程与空天信息国际学术会议(ICAEAI 2026)将于2026年6月26-28日在哈尔滨召开。会议旨在为从事航空航天工程与空天信息领域研究的专家学者、工程技术人员、技术研发人员提供一个共享科研成果和前沿技术,加强学术研究和探讨&…...

CW32驱动S12SD紫外线传感器:I2C通信、数据解析与嵌入式实践

1. 项目概述与核心需求解析最近在做一个户外环境监测的小玩意儿,需要实时监测紫外线强度,选来选去,最终敲定了S12SD这款紫外线传感器模块。之所以选它,一方面是因为它直接输出数字信号,省去了模拟信号调理的麻烦&#…...

Godot-MCP完整指南:如何用AI助手3倍提升游戏开发效率

Godot-MCP完整指南:如何用AI助手3倍提升游戏开发效率 【免费下载链接】Godot-MCP An MCP for Godot that lets you create and edit games in the Godot game engine with tools like Claude 项目地址: https://gitcode.com/gh_mirrors/god/Godot-MCP Godot-…...

Linux包管理核心:yum机制详解与实战配置指南

1. 项目概述:为什么你需要掌握yum?在Linux的世界里,尤其是以Red Hat、CentOS、Fedora为代表的发行版中,yum(Yellowdog Updater, Modified)是每一位系统管理员和开发者绕不开的核心工具。你可以把它想象成一…...

嵌入式开发调试实战:从内存泄漏到死锁的排查技巧与工具链

1. 项目概述:嵌入式开发的“捉虫”艺术干了十几年嵌入式,从8位单片机玩到多核ARM Cortex-A,从裸机撸到RTOS,我最大的感受就是:嵌入式开发,七分在调试,三分在写码。你代码写得再漂亮,…...

Linux存储管理:块设备与分区表的本质区别及实践指南

1. 项目概述:一次关于存储本质的深度对话“我不是表,我是块设备”——这个标题乍一看有点哲学意味,像是在为某个被误解的实体正名。在Linux的世界里,这恰恰揭示了存储管理中一个最核心、也最容易被混淆的概念关系:分区…...

基于离线语音识别的智能化妆镜DIY:STM32控制与PWM调光调色温实战

1. 项目概述:当化妆镜遇上智能语音作为一名折腾过不少智能家居和嵌入式项目的老玩家,我最近完成了一个特别有意思的改造:把家里那面普普通通的化妆镜,升级成了能听懂人话的智能语音化妆镜灯。这玩意儿听起来好像有点“小题大做”&…...

国产ARM主板实战:从设计选型到性能优化的嵌入式开发指南

1. 项目概述:从“能用”到“好用”的国产ARM主板之路最近几年,如果你关注过硬件开发、嵌入式系统或者国产化替代的圈子,一定会频繁听到“国产ARM主板”这个词。它不再是实验室里的样品,而是越来越多地出现在工业控制、边缘计算、智…...

鸿蒙ArkUI视频播放器开发实战:从AVPlayer到自定义控制与性能优化

1. 项目概述:为什么要在鸿蒙上做视频播放器?最近在捣鼓鸿蒙应用开发,发现社区里关于多媒体处理,特别是视频播放的深度分享还不多。很多开发者拿到Video组件,照着官方Demo跑起来一个播放界面就觉得完事了。但真要把一个…...

STM32F103C8T6驱动BMP280气压模块:从I2C地址纠错到数据转换的完整避坑指南

STM32F103C8T6驱动BMP280气压模块:从I2C地址纠错到数据转换的完整避坑指南 在嵌入式开发中,气压传感器BMP280因其高精度和低成本成为许多项目的首选。然而,当这个看似简单的模块遇上STM32F103C8T6这颗经典的MCU时,不少开发者却踩进…...

Python 中的 @property:像访问属性一样调用方法

# Python 中的 property:像访问属性一样调用方法在写类的时候,我们经常会遇到一个问题: 对象的属性如果可以被随便修改,就可能出现一些不合理的数据。比如一个人的年龄:python class Person:def __init__(self, age)…...

从USB转TTL到RS485:手把手教你用一颗CH342F芯片玩转三种串口通信

CH342F芯片实战指南:一芯三用的串口通信解决方案 在物联网和工业控制领域,串口通信依然是设备间可靠数据传输的基石。面对多样化的接口标准(TTL、RS232、RS485),工程师常常需要准备多种转换模块。而CH342F芯片以其独特…...

企业号码认证服务:实现座机、手机来电显示公司名称+品牌LOGO

在如今的商业环境下,一通没有身份标识的电话,想要敲开客户的大门已经变得越来越难。反诈意识的普及,让人们对陌生呼叫筑起了厚厚的防御墙。许多企业在开展客户回访、售后跟进或业务接洽时,频繁遭遇拒接、秒挂的窘境。投入了大笔的…...

STC15单片机定时器T0配置详解:从1T/12T模式选择到1秒精准定时(附完整代码)

STC15单片机定时器T0配置实战:1秒精准定制的全流程解析 从理论到实践的定时器T0深度探索 在嵌入式系统开发中,定时器功能如同系统的心跳,为各类任务提供精准的时间基准。STC15系列单片机凭借其高性能和丰富的外设资源,成为许多开…...

Windows安卓驱动安装终极解决方案:一键自动化ADB Fastboot工具

Windows安卓驱动安装终极解决方案:一键自动化ADB Fastboot工具 【免费下载链接】Latest-adb-fastboot-installer-for-windows A Simple Android Driver installer tool for windows (Always installs the latest version) 项目地址: https://gitcode.com/gh_mirro…...

3步掌握Open-Lyrics:如何让AI为你的音频自动生成专业字幕

3步掌握Open-Lyrics:如何让AI为你的音频自动生成专业字幕 【免费下载链接】openlrc Transcribe and translate voice into LRC file using Whisper and LLMs (GPT, Claude, et,al). 使用whisper和LLM(GPT,Claude等)来转录、翻译你的音频为字幕文件。 项…...

鼎讯 SZT-1000A:交通网络多合一智能测试仪

铁路、高速公路通信网络业务密集、链路复杂,集传输、监控、收费于一体,对测试设备的集成度、便携性、精准度要求极高。鼎讯 SZT-1000A 以太网测试仪,以 “一机多能、超轻便携” 的优势,成为交通领域网络安装、调试、运维的核心利器…...

你的微信聊天记录,真的安全吗?揭秘永久保存数字记忆的开源方案

你的微信聊天记录,真的安全吗?揭秘永久保存数字记忆的开源方案 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHu…...

三星固件下载终极指南:Bifrost跨平台工具完整使用手册

三星固件下载终极指南:Bifrost跨平台工具完整使用手册 【免费下载链接】Bifrost Cross-platform tool for downloading Samsung mobile device firmware. 项目地址: https://gitcode.com/gh_mirrors/sa/Bifrost 还在为三星设备找不到官方固件而烦恼吗&#x…...

【软考高级架构】论文范文22——论系统可靠性设计及其应用

论系统可靠性设计及其应用 论系统可靠性设计及其应用,本文结合2014年试题题目进行深入论述,探讨如何在实际项目中进行软件的可靠性设计,确保系统在复杂和高风险环境下的稳定性与高效性。在现代复杂系统中,软件的可靠性设计已成为保障系统高效稳定运行的关键因素之一。随着技…...

告别网络玄学:手把手教你用寄存器调试法搞定YT8521 PHY‘ping不通’故障

寄存器调试实战:用YT8521 PHY案例解析RGMII时序优化 当一块嵌入式开发板的网络接口出现"能发不能收"的诡异现象时,多数工程师的第一反应往往是检查驱动配置或网线连接。但在实际项目中,这种看似简单的"ping不通"问题&…...

【软考高级架构】案例题考前突击19——微服务架构下的服务注册发现与熔断限流机制设计

案例分析题:微服务架构下的服务注册发现与熔断限流机制设计 案例背景 B公司开发了一套大型电商系统,采用Spring Cloud微服务架构实现商品管理、订单管理、支付服务、用户服务、搜索推荐等多个服务模块。系统部署在Kubernetes平台上,采用Eureka作为服务注册中心,Ribbon和F…...

从无人机炸机到平稳飞行:IMU椭球拟合校准实战避坑指南

从无人机炸机到平稳飞行:IMU椭球拟合校准实战避坑指南 去年夏天,我在郊外测试一台自组装的四轴无人机时,经历了惊心动魄的一幕——起飞不到30秒,飞行器突然失控翻滚,最终坠毁在草地上。拆解排查后发现,问题…...

【软考高级架构】案例题考前突击——分布式一致性在互联网金融平台的应用

案例分析题:分布式一致性在互联网金融平台的应用 案例背景 某互联网金融平台为了满足高并发、高可用的业务需求,采用了基于微服务和分布式架构的系统设计。平台核心业务包括账户余额管理、交易流水记录、资金划转等关键模块。 为提升系统性能,架构师引入了如下关键设计:…...

告别烦人黑窗口!QT Creator控制台程序输出完美嵌入IDE的保姆级设置

告别烦人黑窗口!QT Creator控制台程序输出完美嵌入IDE的保姆级设置 每次调试C控制台程序时,那个突然弹出的黑窗口是否总让你分心?作为开发者,我们都渴望一个纯净的编码环境——所有信息集中在一处,无需在多个窗口间来回…...