从底层设计原理分析并理解SQL 的执行顺序

​一、执行顺序的底层设计原理​​

​​1. 数据源的确定与连接(FROM → ON → JOIN)​​
​​FROM​​:数据库首先需要确定数据的物理来源,从磁盘加载表或子查询的原始数据。此时尚未应用任何筛选,仅读取元数据(如数据块位置)。
​​ON​​:在 JOIN 操作中,ON 条件用于​​连接时的行级过滤​​。例如在多表关联时,ON 会先筛选出满足连接条件的行组合,生成中间结果集。
​​JOIN​​:根据 ON 的条件合并数据,此时可能生成笛卡尔积的中间结果(如未优化的情况)。数据库会优先执行连接操作,因为连接后的数据集规模直接影响后续处理成本。
​​设计意义​​:尽早确定数据关联关系,避免在复杂计算中反复访问磁盘。例如,若两张表各有 100 万行,未经优化的 JOIN 可能产生 1 万亿行中间结果,而先连接再过滤可显著减少后续处理量。

​​2. 行级过滤(WHERE)​​
WHERE 在 JOIN 之后执行,对连接后的中间结果进行​​行级过滤​​。例如 WHERE age > 18 会剔除不满足条件的行。
​​关键限制​​:WHERE 中不能直接使用聚合函数(如 SUM()),因为此时尚未分组。
​​原理优势​​:在数据量最大的阶段(原始表或连接后的中间表)尽早过滤,减少后续处理的行数。例如,若 WHERE 过滤掉 90% 的行,后续 GROUP BY 的计算量将降低一个数量级。

​​3. 分组与聚合(GROUP BY → HAVING)​​
​​GROUP BY​​:按指定列将数据分组,并触发聚合函数(如 COUNT(), SUM())的计算。此时生成分组键和聚合值的映射表。
​​HAVING​​:对分组后的结果进行过滤,类似于 WHERE 但作用于分组数据。例如 HAVING SUM(sales) > 1000 会剔除总销售额不足的组。
​​设计逻辑​​:分组操作需要完整的数据分布信息,因此必须在数据加载和过滤后进行。HAVING 在分组后执行,避免在原始数据上重复计算聚合值。

​​4. 结果投影与去重(SELECT → DISTINCT)​​
​​SELECT​​:最后阶段确定最终返回的列,包括:
列名的别名生效(如 SUM(sales) AS total)
计算表达式(如 price * quantity)
聚合值的最终输出
​​DISTINCT​​:对 SELECT 的结果集去重。由于去重需要完整的结果集,必须在 SELECT 之后执行。
​​性能考量​​:延迟列选择和计算可避免中间阶段的冗余处理。例如,若某列在 WHERE 中未使用,但在 SELECT 中出现,引擎可跳过该列的前期加载。

​​5. 排序与分页(ORDER BY → LIMIT)​​
​​ORDER BY​​:对最终结果集排序。由于排序需要内存或临时文件,放在最后可减少排序的数据量。
​​LIMIT​​:限制返回行数。在排序后执行,确保只保留排名靠前的行。
​​资源优化​​:若先执行 LIMIT 再排序,可能因截断数据导致结果错误。例如 LIMIT 10 配合 ORDER BY 需要先排序全部数据再取前 10 行。

​​二、为何 SELECT 在最后执行?​​

​​1. 延迟计算原则​​
​​避免无效计算​​:若 SELECT 中包含复杂表达式(如 LOWER(name)),但 WHERE 条件过滤掉了大部分行,延迟计算可节省 CPU 资源。
​​覆盖索引优化​​:若查询只需索引列,引擎可直接读取索引树,跳过数据行加载(称为「覆盖索引」)。这种优化依赖于 SELECT 阶段的列选择信息。
​​2. 逻辑一致性​​
​​别名可见性​​:SELECT 中定义的别名(如 total_sales)只能在后续阶段(如 ORDER BY)使用,因为引擎需要先完成列的计算。
​​聚合函数依赖​​:HAVING 中的聚合值必须在 GROUP BY 之后才能确定,而 SELECT 需要基于这些值进行投影。

​​三、执行顺序的例外与优化​​

​​1. 优化器的物理调整​​
虽然逻辑顺序固定,但数据库优化器可能通过​​谓词下推​​(Predicate Pushdown)等技术改变物理执行顺序。例如:

将 WHERE 条件提前到 JOIN 之前,减少连接时的数据量。
将 HAVING 中的过滤合并到 WHERE 中(当条件不依赖分组时)。
​​2. 窗口函数的特殊性​​
窗口函数(如 ROW_NUMBER())在 SELECT 阶段执行,但需要依赖完整的分区数据。其计算晚于 WHERE 和 GROUP BY,但早于 ORDER BY 和 LIMIT。

​​四、总结​​

​​最小化数据处理量​​:通过层层过滤(WHERE → GROUP BY → HAVING),逐步缩减数据集规模。
​​资源高效利用​​:延迟计算(如 SELECT)和按需排序(ORDER BY)减少内存和 CPU 消耗。
​​逻辑一致性​​:确保别名、聚合值等依赖关系正确解析。
这种顺序设计体现了数据库引擎「先粗后细」的处理哲学——从海量原始数据中逐步提炼出精确结果,而非人类直觉的「先选择后处理」。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/79956.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

游戏引擎学习第237天:使用 OpenGL 显示图像

win32_game.cpp: 禁用 PFD_DOUBLEBUFFER 我们正在处理一个新的开发阶段,目标是在使用 OpenGL 渲染的同时能正常通过 OBS 进行直播。昨天我们已经尝试了一整天来解决这个问题,希望能找到一种方式让 OBS 能正确地捕捉到 OpenGL 的窗口画面。虽然我们不确定…

(二)mac中Grafana监控Linux上的MySQL(Mysqld_exporter)

框架:GrafanaPrometheusMysqld_exporter 一、监控查看端安装 Grafana安装-CSDN博客 普罗米修斯Prometheus监控安装(mac)-CSDN博客 1.启动Grafana服务 brew services start grafana 打开浏览器输入http://localhost:3000进入grafana登录…

GitHub 趋势日报 (2025年04月17日)

本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ 📈 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1Anduin2017/HowToCook程序员在家做饭方法指南。Programmer’s guide about how to cook at home (Simplified Chinese onl…⭐ 224…

(一)mac中Grafana监控Linux上的CPU等(Node_exporter 安装使用)

框架:GrafanaPrometheusNode_exporter 机器状态监控(监控服务器CPU,硬盘,网络等状态) Node_exporter安装在被测服务器上,启动服务 各步骤的IP地址要换为被测服务器的IP地址Prometheus.yml的 targets值网页访问的ip部分grafana添加数据源的…

java IO/NIO/AIO

(✪▽✪)曼波~~~~!让曼波用最可爱的赛马娘方式给你讲解吧!(⁄ ⁄•⁄ω⁄•⁄ ⁄) 🎠曼波思维导图大冲刺(先看框架再看细节哦): 📚 解释 Java 中 IO、NIO、AIO 的区别和适用场景: …

Silverlight发展历程(微软2021年已经停止支持Silverlight 5)

文章目录 Microsoft Silverlight 发展历程引言起源与背景(2006-2007)互联网技术格局与微软的挑战WPF/E 项目的启动 Silverlight 1.0 的诞生(2007)正式命名与首次发布初步的市场定位 Silverlight 2.0:真正的突破&#x…

【大数据、数据开发与数据分析面试题汇总(含答案)】

在大数据、数据开发与数据分析领域的面试中,扎实掌握各类知识点至关重要。以下是精心整理的面试题,涵盖单选题和多选题,助你备考一臂之力。 试题目录 大数据、数据开发与数据分析高频面试题解析1. 数据仓库分层架构设计2. 维度建模与范式建模…

Docker部署禅道21.6开源版本

将数据库相关环境变量分开,增加注释或空格使得命令更易读。 如果你的 MySQL 主机、端口等配置没有变化,应该确保这些信息是安全的,并考虑使用 Docker secrets 或环境变量配置来避免直接暴露敏感信息。 docker run -d -it --privilegedtrue …

Yocto项目实战教程 · 第4章:4.2小节-菜谱

🔍 B站相应的视频教程: 📌 Yocto项目实战教程-第4章-4.2小节-菜谱 记得三连,标为原始粉丝。 在 Yocto 项目中,**菜谱(Recipe)**承载了包的配置信息、源码获取方式、编译与安装步骤,是…

【pytorch】torch.nn.Unfold操作

说明 一个代码里涉及到了unfold的操作,看了半天官网都没整明白维度怎么变化的,参考这个链接搞明白了: https://blog.csdn.net/ViatorSun/article/details/119940759 https://zhuanlan.zhihu.com/p/361140988 维度计算 输入( N,…

Linux 固定IP地址

一.查看网口状态: $ ip a 二.配置静态IP文件: $ sudo vi /etc/network/interface auto eth0 iface eth0 inet static address 192.168.0.252 gateway 192.168.0.1 netmask 255.255.255.0 #network 192.168.0.0 #broadcast 192.168.0.255 三.重启网卡让新…

android的 framework 有哪些知识点和应用场景

Android Framework 知识点 1. 四大组件 Activity(活动) 是 Android 应用中最基本的组件,用于实现用户界面。一个 Activity 通常对应一个屏幕的内容。有自己的生命周期,包括 onCreate、onStart、onResume、onPause、onStop、onDe…

如何在PDF.js中改造viewer.html以实现PDF的动态加载

在PDF.js中改造viewer.html实现PDF动态加载,需结合参数传递、文件流处理及跨域配置等技术。以下是综合多个技术方案的核心实现步骤: ​一、基础参数传递法​ 1. ​URL参数动态加载​ 通过修改viewer.html的URL参数传递PDF路径,适用于静态文…

组件之间的数据通信方式

Vue 的传值方式(即组件之间的数据通信方式)根据组件关系不同(父子、兄弟、跨层级)有所区别。下面是常见的传值方式,按使用场景来分类: 一、父子组件传值 1. props(父 -> 子) 父…

组件是怎样写的(1):虚拟列表-VirtualList

本篇文章是《组件是怎样写的》系列文章的第一篇,该系列文章主要说一下各组件实现的具体逻辑,组件种类取自 element-plus 和 antd 组件库。 每个组件都会有 vue 和 react 两种实现方式,可以点击 https://hhk-png.github.io/components-show/ …

个性化的配置AndroidStudio

Android Studio 提供诸多向导和模板,可用于验证 Java 开发套件 (JDK) 和可用 RAM 等系统要求,以及配置默认设置,例如经过优化的默认 Android 虚拟设备 (AVD) 模拟和更新的系统映像。本文档介绍了可用于自定义 Android Studio 使用方式的其他配…

人类行为的原动力是自我保存-来自ChatGPT

自我保存(Self-Preservation)确实可以说是人类行为最原始、最底层的驱动力。 简单来说: 无论我们做什么,表面看动机五花八门,实际上归根到底都绕不开活下去、保护自己。 💡 从不同层面理解这个观点&#…

SystemVerilog语法之内建数据类型

简介:SystemVerilog引进了一些新的数据类型,具有以下的优点:(1)双状态数据类型,更好的性能,更低的内存消耗;(2)队列、动态和关联数组,减少内存消耗…

蓝光三维扫描技术:高效精密测量相机镜头底座注塑件

如今越来越多的摄影爱好者、vlog拍摄者使用数码相机以及无人机,随时随地记录生活中的每一刻美好瞬间,对相机设备的要求也不断提高。 — 案例背景 — 相机镜头底座涉及镜头装置可靠、螺丝位置度连接以及壳体组装,镜头底座注塑件生产厂商&…

【前端】【面试】【业务场景】前端如何获取并生成设备唯一标识

✅ 总结 问题:前端如何获取并生成设备唯一标识? 核心要点:浏览器原生信息有限,但通过组合多个维度可生成设备指纹(Device Fingerprint),用于唯一标识设备。 常见方式: 浏览器信息&…