MySQL查询优化器底层原理解析:从逻辑优化到物理优化
MySQL查询优化器底层原理解析:从逻辑优化到物理优化
引言
在数据库系统中,SQL语句的执行效率直接影响着整个应用的性能表现。一条普通的SQL执行前会经历五个关键阶段:SQL输入、语法分析、语义检查、SQL优化、SQL执行。其中,SQL优化又分为逻辑优化和物理优化两个步骤。本文将深入探讨MySQL查询优化器的底层工作原理,帮助开发者更透彻地理解SQL优化器的工作机制,为慢查询优化提供更多分析依据。
查询优化器架构概览
SQL执行流程中有一个核心模块叫做查询优化器,其主要功能是对SQL语法树进行逻辑优化和物理优化,最终生成执行计划交给执行引擎执行。查询优化器主要分为两部分:
-
逻辑优化:将SQL语法树中的谓词转化为逻辑代数操作符,把语法树转化为关系代数语法树,然后进行语义优化、子查询优化、裁减冗余操作、连接提取公共表达式等一系列优化,最后生成逻辑查询执行计划。
-
物理优化:在逻辑优化后继续对SQL语法树进行改造,对多表连接的顺序进行调整,使用代价估算器对单表扫描和多表连接顺序进行代价评估,选择代价最小的方案作为优化基础,最后生成物理查询执行计划。
逻辑查询优化详解
子查询优化
子查询在日常SQL编写中很常见,但执行效率往往较低。早期的MySQL对子查询采用嵌套执行方式,父查询每查询一行就执行一次子查询,效率极差。优化器对子查询进行了多种优化:
- 子查询转为连接操作:将子查询转变为连接操作,减少执行次数,并将子查询条件转化为父查询条件下推。
-- 原子查询
select * from a where col_1 in (select col_1 from b);
-- 转为内连接
select a.* from a inner join b on a.col_1 = b.col_1;
-
半连接(Semi-Join):保留a表在b表存在匹配的记录,不关心b表有多少条匹配记录。MySQL提供了临时表和首次匹配策略两种实现方式。
-
派生表优化:将FROM子句中的子查询(派生表)上拉优化为内连接。
-- 派生表
select * from (select * from a where col_1 = 1) as t inner join b on t.col_1 = b.col_1;
-- 优化后
select * from a inner join b on a.col_1 = b.col_1 where a.col_1 = 1;
等价谓词重写
优化器会对多种谓词进行重写,使其能够利用索引提高效率:
- LIKE重写:将LIKE模糊查询转为范围查询。
select * from a where col_1 like 'abc%';
-- 重写为
select * from a where col_1 >= 'abc' and col_1 <= 'abd';
- BETWEEN-AND重写:转为简单的比较表达式。
select * from a where col_1 between 1 and 10;
-- 重写为
select * from a where col_1 >= 1 and col_1 <= 10;
- IN/OR重写:将IN谓词转为OR表达式或ANY函数。
select * from a where col_1 in (1,2,3);
-- 重写为
select * from a where col_1 = 1 or col_1 = 2 or col_1 = 3;
条件化简
优化器会对查询条件进行多种化简操作:
- 条件下推:将过滤条件尽可能下推到基表扫描阶段。
select * from a,b where a.col_1=b.col_1 and a.col_2=2;
-- 优化后先扫描a表时带上a.col_2=2条件
- HAVING并入WHERE:无GROUP BY时合并HAVING和WHERE条件。
select * from a where col_1>1 having col_2=3;
-- 优化为
select * from a where col_1>1 and col_2=3;
- 常量传递:通过等式传递优化条件。
select * from a where col_1=col_2 and col_2=2;
-- 优化为
select * from a where col_1=2 and col_2=2;
连接优化
- 外连接消除:当外连接的WHERE条件包含内表列的非空判断时,可优化为内连接。
select * from a left outer join b on a.col_1 = b.col_1 where b.col_1 is not null;
-- 优化为内连接
select * from a,b where a.col_1 = b.col_1;
- 嵌套连接消除:对于纯内连接的嵌套可以消除括号并交换连接顺序。
select * from a join (b join c on b.col_2=c.col_2) on a.col_1=b.col_1;
-- 优化为
select * from a join b on a.col_1=b.col_1 join c on b.col_2=c.col_2;
- 连接消除:主外键关系或多表连接列都有唯一索引时可消除中间表。
-- b.col_1是主键,a.col_1是外键
select a.*,c.* from a join b on a.col_1 = b.col_1 join c on b.col_1 = c.col_1;
-- 优化为
select a.*,c.* from a join c on a.col_1 = c.col_1;
分组排序优化
- GROUP BY优化:根据代价评估选择分组操作下移或上移。
- ORDER BY优化:利用索引排序消除排序操作,或下推排序到基表。
- DISTINCT优化:利用索引去重或将去重操作迁移到子查询。
- LIMIT优化:与ORDER BY、DISTINCT等结合时的特殊优化策略。
物理查询优化详解
代价估算模型
物理优化的核心是代价估算模型,其公式为:
总代价 = IO代价 + CPU代价
COST = P*a_page_cpu_time + W*T
其中:
- P:访问的页面数
- a_page_cpu_time:读取每个页面的时间
- W:选择率(满足条件的记录数/总记录数)
- T:访问的记录数
单表扫描算法
- 顺序扫描:直接读取表中的数据,适合小数据量。
- 索引扫描:通过索引定位记录,选择率<0.1时效果较好。
- 只读索引扫描:覆盖索引避免回表查询。
- 行扫描:通过特殊列直接定位行数据。
- 并行扫描:并行顺序或索引扫描。
- 组合索引扫描:对多条件查询进行多次索引扫描。
两表连接算法
-
嵌套循环连接:
- 基本嵌套循环:效率差,基本被淘汰
- 基于索引的嵌套循环:内表连接列有索引
- BNL算法:通过join buffer减少内表扫描次数
- BKA算法:结合MRR技术解决随机IO问题
-
排序归并连接:对已排序的表进行归并连接,适合大数据量。
-
Hash连接:用连接列作为hash键,适合等值连接且内表数据量适中。
多表连接算法
多表连接顺序组合随表数N呈阶乘增长(N!)。MySQL采用两种算法:
-
动态规划算法:PostgreSQL采用,穷举所有可能选择最优解。
- 树叶层:评估单表扫描代价
- 第二层:两表连接评估
- 第三层:三表连接评估
- 依次类推直到解决整个问题
-
贪婪算法:MySQL采用,每次选择局部最优解,不一定全局最优但效率高。
总结
MySQL查询优化器通过逻辑优化和物理优化两个阶段,对SQL查询进行全方位优化:
- 逻辑优化:通过子查询优化、等价谓词重写、条件化简、连接优化等手段,重写查询逻辑使其更高效。
- 物理优化:通过代价模型评估,选择最优的单表扫描方式、两表连接算法和多表连接顺序。
理解这些底层原理,可以帮助开发者在编写SQL时更有针对性,也能更有效地分析和优化慢查询。正如《阿里巴巴编码规范》建议的,多表连接时应控制表数量在3个以内,因为连接顺序组合会随表数呈阶乘增长,导致优化器评估代价急剧增加。
相关文章:
MySQL查询优化器底层原理解析:从逻辑优化到物理优化
MySQL查询优化器底层原理解析:从逻辑优化到物理优化 引言 在数据库系统中,SQL语句的执行效率直接影响着整个应用的性能表现。一条普通的SQL执行前会经历五个关键阶段:SQL输入、语法分析、语义检查、SQL优化、SQL执行。其中,SQL优…...
UI架构的历史与基础入门
本笔记的目的是通过一系列连贯的例子来探讨“事物-模型-视图-编辑器”这一隐喻。 这些例子都来自我的规划系统(planning system),用于解释上述四个概念。所有例子都已实现,但并未在本文描述的清晰类结构中实现。 这些隐喻对应于《…...
(三)MMA(KeyCloak身份服务器/OutBox Pattern)
文章目录 项目地址一、KeyCloak二、OutBox Pattern2.1 配置Common模块的OutBox1. OutboxMessage2. 数据库配置OutboxMessageConfiguration3. 创建Save前的EF拦截器4. 创建Quartz后台任务5. 配置后台任务6. 注册服务2.2 创建OutBox的消费者项目地址 教程作者:教程地址:代码仓库…...
【通用智能体】Playwright:跨浏览器自动化工具
Playwright:跨浏览器自动化工具 一、Playwright 是什么?二、应用场景及案例场景 1:端到端(E2E)测试场景 2:UI 自动化(表单批量提交)场景 3:页面截图与 PDF 生成场景 4&am…...
单片机设计_停车场车位管理系统(AT89C52、LCD1602)
想要更多项目私wo!!! 一、电路设计 此电路由AT89C52单片机和LCD1602液晶显示模块等器件组成。 二、运行结果 三、部分代码 #include <reg52.h> //调用单片机头文件 #define uchar unsigned char //无符号字符型 宏定义 变量范围0~255 #define uint unsigned…...
【android bluetooth 协议分析 01】【HCI 层介绍 5】【SetEventMask命令介绍】
1. HCI_Set_Event_Mask 命令作用 项目内容命令名HCI_Set_Event_MaskOCF0x0001作用主机通过设置 Event Mask 告诉控制器:我只对某些事件感兴趣,屏蔽其他事件,以减少中断。事件来源事件是 HCI 与主机之间通信的反馈机制,控制器通过…...
python打卡day29
类的装饰器 知识点回顾 类的装饰器装饰器思想的进一步理解:外部修改、动态类方法的定义:内部定义和外部定义 回顾一下,函数的装饰器是 :接收一个函数,返回一个修改后的函数。类也有修饰器,类装饰器本质上确…...
【数据结构】树状数组
树状数组 假设一个数可以 x x x可以被二进制分解成 x 2 i 1 2 i 2 . . . 2 i m x 2^{i_1} 2^{i_2} ... 2^{i_m} x2i12i2...2im,不妨设 i 1 > i 2 > . . . > i m i_1 > i_2 > ... > i_m i1>i2>...>im,进…...
Java虚拟机 - JVM与Java体系结构
Java虚拟机 JVM与Java体系结构为什么要学习JVMJava与JVM简介Java 语言的核心特性JVM:Java 生态的基石JVM的架构模型基于栈的指令集架构(Stack-Based)基于寄存器的指令集架构(Register-Based)JVM生命周期 总结 JVM与Jav…...
翻译:20250518
翻译题 文章目录 翻译题一带一路中国结 一带一路 The “One Belt and One Road” Initiative aims to achieve win-win and shared development. China remains unchanged in its commitment to foster partnerships. China pursues an independent foreign policy of peace, …...
SparkSQL基本操作
以下是 Spark SQL 的基本操作总结,涵盖数据读取、转换、查询、写入等核心功能: 一、初始化 SparkSession scala import org.apache.spark.sql.SparkSession val spark SparkSession.builder() .appName("Spark SQL Demo") .master("…...
Ansible模块——文件内容修改
修改文件单行内容 ansible.builtin.lineinfile 可以按行修改文件内容,一次修改一行,支持正则表达式。 选项名 类型 默认值 描述 attributesstrnull 设置目标文件的 Linux 文件系统属性(attribute bits),作用类似于…...
基于单片机路灯自动控制仪仿真设计
标题:基于单片机路灯自动控制仪仿真设计 内容:1.摘要 本设计旨在解决传统路灯控制方式效率低、能耗大的问题,开展了基于单片机的路灯自动控制仪仿真设计。采用单片机作为核心控制单元,结合光照传感器、时钟模块等硬件,运用相关软件进行编程和…...
Spring Web MVC————入门(3)
今天我们来一个大练习,我们要实现一个登录界面,登录进去了先获取到登录人信息,可以选择计算器和留言板两个功能,另外我们是学后端的,对于前端我们会些基础的就行了,知道ajax怎么用,知道怎么关联…...
拓展运算符与数组解构赋值的区别
拓展运算符与数组解构赋值是ES6中用于处理数组的两种不同的特性,它们有以下区别: 概念与作用 • 拓展运算符:主要用于将数组展开成一系列独立的元素,或者将多个数组合并为一个数组,以及在函数调用时将数组作为可变参…...
【Linux】第二十章 管理基本存储
目录 1. 对 Linux 磁盘进行分区时有哪两种方案?分别加以详细说明。 2. 简单说下创建MBR磁盘分区涉及哪几个步骤? 3. 创建GPT分区与创建MBR分区有什么不同? 4. 在创建分区时就会在分区上创建文件系统吗? 5. 如何持久挂载文件系…...
DeepSeek本地部署全攻略:从零搭建到Web可视化及数据训练
目录 1. 环境准备与硬件要求2. 安装Ollama框架3. 部署DeepSeek模型4. Web可视化配置5. 数据投喂与模型训练6. 进阶技巧与常见问题1. 环境准备与硬件要求 硬件配置建议 基础配置:16GB内存 + RTX 3060显卡(流畅运行7B参数模型)进阶配置:32GB内存 + RTX 4090显卡(支持14B模型…...
JavaScript性能优化实战(12):大型应用性能优化实战案例
在前面的系列文章中,我们探讨了各种JavaScript性能优化技术和策略。本篇将聚焦于实际的大型应用场景,通过真实案例展示如何综合运用这些技术,解决复杂应用中的性能挑战。 目录 电商平台首屏加载优化全流程复杂数据可视化应用性能优化案例在线协作工具的实时响应优化移动端W…...
前缀和——中心数组下标
此题我们不应局限于前缀和的模板,因为该中心下标把数组分为两个部分且每个部分都要求和,我们就一个再创建一个”后缀和” 定义两个数组f,g。f[i]表示[0,i-1]所有元素的和 f[i]f[i-1]nums[i-1];g[i]表示[i1,n-1]的和 g[i]g[i1]nums[i1];因为依…...
Java——创建多线程的四种方式
一、继承Thread 步骤 1.定义一个类继承Thread 2.重写run方法,在方法中设置线程任务(此线程具体执行的代码) 3.创建自定义线程类对象 4.调用Thread中的start方法,开启线程,jvm自动调用run方法 常用方法 void sta…...
广域网学习
PPPoE技术(拨号上网) PPPoE ( PPP over Ethernet ,以太网承载 PPP 协议)是一种把 PPP 帧封装到以太网帧中的链路层协议。 PPPoE 可以使以太网网络中的多台主机连接到远端的宽带接入服务器。 应用场景 PPPoE 组网结构采…...
inverse-design-of-grating-coupler-3d
一、设计和优化3D光栅耦合器 1.1 代码讲解 通过预定义的环形间距参数(distances数组),在FDTD中生成椭圆光栅结构,并通过用户交互确认几何正确性后,可进一步执行参数扫描优化。 # os:用于操作系统相关功能(如文件路径操作) import os import sys# lumapi:Lumerical 的…...
渗透测试流程-中篇
#作者:允砸儿 #日期:乙巳青蛇年 四月廿一(2025年5月18日) 今天笔者带大家继续学习,网安的知识比较杂且知识面很广,这一部分会介绍很多需要使用的工具。会用各种工具是做网安的基础,ok咱们继续…...
2026武汉门窗门业移门木门铝艺门智能锁展会3月国博举办
展出面积:60000㎡ 观众:80000人次 参展企业:800 专业活动:20 2026武汉门窗门业移门木门铝艺门智能锁展会3月国博举办 2026第二届中国武汉整装定制家居暨门窗装饰材料博览会/2026武汉建博会 时间:2026年3月20-22日 …...
如何用mockito+junit测试代码
Mockito 是一个流行的 Java 模拟测试框架,用于创建和管理测试中的模拟对象(mock objects)。它可以帮助开发者编写干净、可维护的单元测试,特别是在需要隔离被测组件与其他依赖项时。 目录 核心概念 1. 模拟对象(Mock Objects) 2. 打桩(Stubbing) 3. 验…...
31、魔法生物图鉴——React 19 Web Workers
一、守护神协议(核心原理) 1. 灵魂分裂术(线程架构) // 主组件中初始化Workerconst workerRef useRef(null);useEffect(() > {workerRef.current new Worker(new URL(./creatureWorker.js, import.meta.url));workerRef.…...
洛谷题目:P4052 [JSOI2007] 文本生成器 题解 本题(极难)
个人介绍: 题目传送门: P4052 [JSOI2007] 文本生成器 - 洛谷 (luogu.com.cn) 前言: 这道题要求计算长度为 m 的文章中,至少包含一个给定单词的可读文章的数量,并且结果需要对 10007 取模。下面是小亦为大家逐步分析解题思路: 题目整体思路: 为了方便计算…...
【Linux】命令行参数和环境变量
目录 一、命令行参数 二、环境变量 (一)PATH (二)查看环境变量 (三)获取环境环境变量 (四)为什么要环境变量 (五)环境变量特点总结 (1&am…...
AGI大模型(23):LangChain框架快速入门之LangChain介绍
1 什么是LangChain? LangChain是一个基于大语言模型用于构建端到端语言模型应用的框架,它提供了一系列工具、套件和接口,让开发者使用语言模型来实现各种复杂的任务,如文本到图像的生成、文档问答、聊天机器人等。 官网地址:https://python.langchain.com/docs/introduc…...
vmware虚拟机运行多个产生卡顿问题
最近在工作中使用电脑运行两个虚拟机,用来测试程序。运行的时候发现电脑会非常卡顿。导致调试工作进行到一半就会闪退卡死。 首先尝试的解决方案是开一个虚拟机,然后在windows上部署测试程序,后面发现操作很受限制。然后使用windows管…...
八股碎碎念01——HashMap原理
Java面试题周总结 HashMap HashMap实现原理 Java 1.7版本 在Java1.7中HashMap通过数组链表的方式实现,由于链表查询速度为O(n),因此在插入大量元素后查询速度会明显降低。 Java 1.8版本 在Java1.8中对HashMap进行改进,采用数组链表/红黑…...
长篇小说《白鹿原》原著版本在当当网可购到
著名作家陈忠实所真实描写上世纪1959年、1960年、1961年我国三年饥荒时人吃人的长篇小说《白鹿原》原著版本,现能在当当网上购到,价格仅26元。特此推荐。 笔者是从那段不堪回首的饥饿历史中幸存下来的过来人,也是在改革开放初期的文艺复兴年代…...
ColorAid —— 一个面向设计师的色盲模拟工具开发记
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 起因:CodeBuddy,说干就干 起初只是一个随口的想法——我想做一个“色盲辅助工具”&…...
对称加密与非对称加密在 JWT 中的应用详解
文章目录 对称加密与非对称加密在 JWT 中的应用详解引言对称加密与非对称加密概述对称加密(Symmetric Encryption)非对称加密(Asymmetric Encryption) 对称加密生成和验证 JWT 的过程生成 JWT(HS256 示例)验…...
Python 中 if 和 else 基础知识的详解和使用
一、基本语法结构 if 条件1:# 条件1 为真时执行的代码块 elif 条件2:# 条件1 不成立,条件2 成立时执行 else:# 所有条件都不成立时执行注意: elif 是“else if”的缩写,可以有多个;else 可省略;条件表达式必须是可以…...
学习黑客Active Directory 入门指南(三)
Active Directory 入门指南(三):关键服务、用户与组管理 🤝💻 大家好!欢迎来到 “Active Directory 入门指南” 系列的第三篇。在前两篇中,我们已经了解了AD的基本概念、逻辑结构(对…...
10.9 LangChain LCEL革命:43%性能提升+声明式语法,AI开发效率飙升实战指南
LangChain 表达式语言(LCEL)架构解析:新一代链式编排引擎 关键词:LangChain Expression Language, Runnable 协议, 链式编排, 并行处理, 生产级应用开发 1. LCEL 设计理念与技术突破 LangChain Expression Language(LCEL)是 LangChain v0.3 的核心革命性升级,重新定义…...
一文读懂-嵌入式Ubuntu平台
现在直接在一些嵌入式Soc上移植ubuntu来用到产品上,刚开始感觉还挺臃肿的,后来细聊了下感觉还是有一定的优势。 ubuntu相信大家在熟悉不过了,几乎无处不在,小到咖啡机,大到火星车,为什么ubuntu如此广泛&am…...
centos7.9扩展已有分区空间
新增50G硬盘 分区 fdisk /dev/sdb Command (m for help): p #打印分区表Disk /dev/sdb: 53.7 GB, 53687091200 bytes, 104857600 sectors Units sectors of 1 * 512 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 byte…...
ubuntu22.04搭建ROS2环境
在 Ubuntu 22.04 上安装 ROS 2(Humble Hawksbill)时,针对国内网络问题,建议使用镜像源加速。以下是分步指南: 1. 更换 Ubuntu 系统源(使用清华镜像) sudo sed -i "shttp://.*archive.ubunt…...
java中sleep()和wait()暂停线程的区别
1. Thread.sleep() 所属类:它是Thread类的静态方法。作用:让当前正在执行的线程暂停指定的时间,在暂停期间,线程会一直持有对象锁(也就是synchronized锁)。中断响应:当线程处于sleep()状态时&a…...
printf函数参数与入栈顺序
01. printf()的核心功能 作用:将 格式化数据 输出到 标准输出(stdout),支持多种数据类型和格式控制。 int printf(const char *format, ...);参数: format:格式字符串,字符串或%开头格式符...:…...
代码案例分析
以下是一个使用线性回归进行简单房价预测的机器学习代码案例分析: 代码示例 import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split # 生成一些示例数据…...
Baklib赋能企业知识资产AI化升级
AI驱动知识管理革新 在数字化转型浪潮中,企业知识管理的范式正经历AI技术的深度重构。传统知识库受限于静态存储与人工维护,而Baklib通过构建知识中台架构,将多模态数据处理与语义理解引擎深度融合,实现知识资产的动态聚合与智能…...
Leetcode 3552. Grid Teleportation Traversal
Leetcode 3552. Grid Teleportation Traversal 1. 解题思路2. 代码实现 题目链接:3552. Grid Teleportation Traversal 1. 解题思路 这一题的话核心就是一个广度优先遍历,我们只需要从原点开始,一点点考察其所能到达的位置,直至…...
【Bluedroid】蓝牙HID DEVICE 报告发送与电源管理源码解析
本文基于Android蓝牙协议栈代码,深度解析HID设备(如键盘、鼠标)从应用层发送输入报告到主机设备的完整流程,涵盖数据封装、通道选择、L2CAP传输、电源管理四大核心模块。通过函数调用链(send_report → BTA_HdSendRepo…...
day15-进程管理
1. 概述 运行起来的软件就是进程,在内存中运行守护进程/服务:一直运行的进程 2. 僵尸进程 2.1. 僵尸进程zombie 当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸…...
抖音视频下载工具 v1.1 自用分享
用免费的公益接口用AI写了个简单的抖音视频下载工具,自用的,不支持批量下载 内置两套API,解析失败会自动切换,支持视频预览播放,视频截图等操作 使用方法也很简单: 软件打开后会监听粘贴板,当检…...
46、什么是Windows服务,它的⽣命周期与标准的EXE程序有什么不同?
Windows服务是一种在Windows操作系统后台运行的特殊应用程序,与标准的EXE程序相比,其生命周期在启动方式、运行持续性、用户交互、运行账户、管理方式、进程状态及开发要求等方面存在显著差异。以下是对Windows服务及其与标准EXE程序生命周期差异的详细分…...
用 UniApp 构建习惯打卡 App —— HabitLoop 开发记
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 当我脑海中突然冒出一个念头:“做一个自己能每天打卡的习惯 App 吧”,我立刻打开了 Cod…...