SQL的查询优化

article/2025/8/23 13:19:22

1. 查询优化器

1.1. SQL语句执行需要经历的环节

  • 解析阶段:语法分析和语义检查,确保语句正确;
  • 优化阶段:通过优化器生成查询计划;
  • 执行阶段:由执行器根据查询计划实际执行操作。

1.2. 查询优化器

查询优化器的概念:

查询优化器的作用是为 SQL 查询生成最优的执行计划。其内部通常分为两个阶段:

1. 逻辑优化

  • 基于关系代数进行等价重写(如谓词下推、连接重写、视图展开);
  • 目的是生成多个逻辑上等价但执行效率不同的候选计划。

2. 物理优化

  • 为逻辑计划选择具体的物理操作(如全表扫描 vs 索引扫描,嵌套循环连接 vs 哈希连接);
  • 通过代价估算模型选出代价最小的执行路径。

查询优化器的两种优化方式:

  1. 第一种是基于规则的优化器RBO,Rule-Based Optimizer),规则就是人们以往的经验,或者是采用已经被证明是有效的方式。通过在优化器里面嵌入规则,来判断 SQL 查询符合哪种规则,就按照相应的规则来制定执行计划,同时采用启发式规则去掉明显不好的存取路径。
  2. 第二种是基于代价的优化器CBO,Cost-Based Optimizer),这里会根据代价评估模型,计算每条可能的执行计划的代价,也就是 COST,从中选择代价最小的作为执行计划。相比于 RBO 来说,CBO 对数据更敏感,因为它会利用数据表中的统计信息来做判断,针对不同的数据表,查询得到的执行计划可能是不同的,因此制定出来的执行计划也更符合数据表的实际情况。

RBO 的方式更像是一个出租车老司机,凭借自己的经验来选择从 A 到 B 的路径。而 CBO 更像是手机导航,通过数据驱动,来选择最佳的执行路径。

1.3. CBO 的代价估算机制

1. 代价模型

能调整的代价模型的参数:

MySQL 中的COST Model就是优化器用来统计各种步骤的代价模型,MySQL 会引入两张数据表,里面规定了各种步骤预估的代价(Cost Value) ,我们可以从mysql.server_costmysql.engine_cost这两张表中获得这些步骤的代价:

SQL > SELECT * FROM mysql.server_cost


server_cost 数据表是在 server 层统计的代价,具体的参数含义如下:

  1. disk_temptable_create_cost,表示临时表文件(MyISAM 或 InnoDB)的创建代价,默认值为 20。
  2. disk_temptable_row_cost,表示临时表文件(MyISAM 或 InnoDB)的行代价,默认值 0.5。
  3. key_compare_cost,表示键比较的代价。键比较的次数越多,这项的代价就越大,这是一个重要的指标,默认值 0.05。
  4. memory_temptable_create_cost,表示内存中临时表的创建代价,默认值 1。
  5. memory_temptable_row_cost,表示内存中临时表的行代价,默认值 0.1。
  6. row_evaluate_cost,统计符合条件的行代价,如果符合条件的行数越多,那么这一项的代价就越大,因此这是个重要的指标,默认值 0.1。

在存储引擎层都包括了哪些代价:

SQL > SELECT * FROM mysql.engine_cost


engine_cost主要统计了页加载的代价,一个页的加载根据页所在位置的不同,读取的位置也不同,可以从磁盘 I/O 中获取,也可以从内存中读取。因此在engine_cost数据表中对这两个读取的代价进行了定义:

  1. io_block_read_cost,从磁盘中读取一页数据的代价,默认是 1。
  2. memory_block_read_cost,从内存中读取一页数据的代价,默认是 0.25。

通过SQL语句调整以上参数:

MySQL 将这些代价参数以数据表的形式呈现给了我们,我们就可以根据实际情况去修改这些参数。因为随着硬件的提升,各种硬件的性能对比也可能发生变化,比如针对普通硬盘的情况,可以考虑适当增加io_block_read_cost的数值,这样就代表从磁盘上读取一页数据的成本变高了。当我们执行全表扫描的时候,相比于范围查询,成本也会增加很多。

io_block_read_cost参数设置为 2.0,使用下面这条命令:

UPDATE mysql.engine_costSET cost_value = 2.0WHERE cost_name = 'io_block_read_cost';
FLUSH OPTIMIZER_COSTS;


我们对mysql.engine_cost中的io_block_read_cost参数进行了修改,然后使用FLUSH OPTIMIZER_COSTS更新内存,然后再查看engine_cost数据表,发现io_block_read_cost参数中的cost_value已经调整为 2.0。

专门针对某个存储引擎,比如 InnoDB 存储引擎设置io_block_read_cost,设置为 2:

INSERT INTO mysql.engine_cost(engine_name, device_type, cost_name, cost_value, last_update, comment)VALUES ('InnoDB', 0, 'io_block_read_cost', 2,CURRENT_TIMESTAMP, 'Using a slower disk for InnoDB');
FLUSH OPTIMIZER_COSTS;

再查看一下mysql.engine_cost数据表:

2. 总代价计算方式

可以简单地认为,总的执行代价等于 I/O 代价 +CPU 代价。在这里 PAGE FETCH 就是 I/O 代价,也就是页面加载的代价,包括数据页和索引页加载的代价。W*(RSI CALLS) 就是 CPU 代价。W 在这里是个权重因子,表示了 CPU 到 I/O 之间转化的相关系数,RSI CALLS 代表了 CPU 的代价估算,包括了键比较(compare key)以及行估算(row evaluating)的代价。

总代价 = I/O 代价 + CPU 代价 [+ 内存代价 + 远程访问代价]
  • I/O 成本:页的加载,如索引页和数据页;
  • CPU 成本:如行过滤、键比较等操作;
  • W × RSI Calls:W 是 CPU/I/O 的权重因子,RSI Calls 是逻辑计算量。

2. 使用性能分析工具定位SQL执行慢的原因

2.1. 数据库服务器的优化步骤

整个流程划分成了观察(Show status)和行动(Action)两个部分。字母 S 的部分代表观察(会使用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。

2.2. 三种性能分析工具

工具

功能

慢查询日志

定位慢 SQL 语句

EXPLAIN

分析执行计划与索引使用情况

SHOW PROFILE

分析执行过程中各步骤的时间开销

1. 慢查询日志分析(Slow Query Log)

        1. 查看是否启用慢查询日志:

SHOW VARIABLES LIKE '%slow_query_log%';

        2. 启用慢查询日志:

SET GLOBAL slow_query_log = 'ON';
  1. 查看/设置慢查询时间阈值:
SHOW VARIABLES LIKE '%long_query_time%';
SET GLOBAL long_query_time = 3;  -- 单位为秒

        3. 使用 mysqldumpslow 工具分析慢查询日志:

perl mysqldumpslow.pl -s t -t 2 /路径/slow.log

参数

含义

-s

排序方式(t:时间,c:次数,r:返回行数)

-t

显示前几条

-g

正则匹配(不区分大小写)

        4. 使用 EXPLAIN 分析 SQL 执行计划

示例:

EXPLAIN SELECT ... FROM table JOIN table2 ON ...

常见字段说明:

字段

含义

id

查询执行顺序,越大越早执行

select_type

查询类型(SIMPLE、PRIMARY、SUBQUERY)

table

正在访问的表

type

访问方式(越靠前越好)

key

实际使用的索引

rows

预估扫描行数

Extra

额外信息,如是否使用索引覆盖、临时表、排序等

数据表的访问类型:

  • 效率从低到高依次为 all < index < range < index_merge < ref < eq_ref < const/system。

2. 使用 SHOW PROFILE 分析查询时间

        1. 开启 profiling:

SET profiling = 1;

        2. 执行要分析的 SQL:

SELECT * FROM ...;

        3. 查看分析结果:

SHOW PROFILES;
SHOW PROFILE FOR QUERY [query_id];

步骤

说明

SHOW PROFILES

显示最近查询的耗时

SHOW PROFILE FOR QUERY N

显示第 N 条查询的各阶段耗时

解决MySQL中长连接内存占用太大的问题:

  1. 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
  2. 如果你用的是 MySQL 5.7 或更新版本,可以在每次执行一个比较大的操作后,通过执行 mysql_reset_connection 来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态。

http://www.hkcw.cn/article/jPnmIrJMaw.shtml

相关文章

为什么在我的Flask里面有两个路由,但是在网页里有一个却不能正确访问到智能体

1. /zhoushibo 能访问&#xff0c;/chat 直接浏览器访问报 Method Not Allowed 原因&#xff1a; /zhoushibo 路由是你用 app.route(/zhoushibo) 定义的&#xff0c;返回的是一个HTML网页&#xff0c;浏览器访问没问题。 /chat 路由你用的是 app.route(/chat, methods[POST])…

【笔记】suna部署之获取 Tavily API key

#工作记录 Tavily 注册 Tavily 账号5&#xff1a; 打开浏览器&#xff0c;访问 Tavily 官网Tavily AI。点击页面上的 “注册” 按钮&#xff0c;按照提示填写注册信息&#xff0c;如邮箱地址、设置密码等&#xff0c;完成注册流程。也可以选择使用 Google 或 GitHub 账号授权登…

openbmc kvm vnc client connection

1. VNC 介绍&#xff1a; VNC&#xff08;Virtual Network Computing&#xff0c;虚拟网络计算&#xff09; 是一种远程桌面协议&#xff08;RDP 的替代方案&#xff09;&#xff0c;允许用户通过网络控制另一台计算机的图形界面。其核心特点是 跨平台、开源、基于帧缓冲&…

OpenEuler 22.03 安装 nacos 2.5.1 集群

零&#xff1a;规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器&#xff0c;用于搭建 nacos 集群。这里使用 2.5.1版本 的原因&#xff0c;是因为它是2.x当前的稳定版本 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.15…

ES中must与filter的区别

在 Elasticsearch 的布尔查询&#xff08;bool query&#xff09;中&#xff0c;must 和 filter 是两个核心子句&#xff0c;它们的核心区别在于 是否影响相关性评分&#xff0c;这直接决定了它们在查询性能、使用场景和结果排序上的差异。以下是详细对比&#xff1a; 一、核心…

MATLAB源代码——基于Rao检验的自适应贝叶斯检测器

此代码适用于信号检测问题,如雷达信号检测、通信系统中的信号存在性检测等。需要根据实际应用调整噪声模型、信号模型以及检测门限的定义。文章目录 MATLAB源代码代码解释以下是基于 Rao 检验 的 自适应贝叶斯检测器 的一个 MATLAB 示例例程。这个例程假设检测问题为高斯分布下…

2025推客系统小程序开发:独立部署源码交付,高性价比裂变增长引擎

在私域流量争夺白热化的今天&#xff0c;源码独立部署的推客系统小程序已成为企业构建自主分销体系、降低获客成本的核心利器。基于成熟案例与技术沉淀&#xff0c;我们提供安全可控、高性价比的一站式解决方案&#xff0c;助力企业快速搭建专属推客生态&#xff0c;实现长效增…

多家医院回应药企向医生行贿 调查正在进行中

近日,一则关于某药企被举报向四川多家医院上百名医生行贿的消息引发广泛关注。举报材料提及四川省内包括成都市、绵阳市、广安市在内的多个城市的医疗机构,共计37家。达州市第一人民医院工作人员表示,举报信中提到的医生在院方员工名单中并不存在。成都医学院第一附属医院和…

The CTeX fontset “fandol“ is unavailable in the current mode.

完整报错如下 The error message says that the CTeX fontset "fandol" is unavailable in the current mode. This usually happens when using the ctex package with pdfLaTeX, but the Fandol fonts are not installed or not supported in this mode. A commo…

贵州一公路落石 汽车被砸中坠落高坎 地质灾害点雨后事故

贵州一公路落石 汽车被砸中坠落高坎 地质灾害点雨后事故!5月28日,贵州毕节市七星关区何官屯镇一条通村公路突发落石。一块约300斤重的巨石砸中一辆过路汽车,导致车辆从路边高坎坠落。司机受轻伤,送医检查后当日返家,车损由保险公司处理。落石还击碎了附近民房的玻璃门,但…

端午民航出行延续“量价齐升” 入境游火爆

端午民航出行延续“量价齐升” 入境游火爆。端午假期临近,位于五一旅游热潮与暑期旺季之间,今年的端午出行市场展现出独特节奏。受假期时长、高考临近等因素影响,旅客出行以周边游为主,同时出入境市场亮点频现,机票价格延续五一假期热度,同比增长。铁路方面,据上铁集团发…

[网页五子棋][匹配模块]处理开始匹配/停止匹配请求(匹配算法,匹配器的实现)

文章目录 处理开始匹配/停止匹配请求匹配算法实现匹配器(1)完善匹配器的 TODO 实现匹配器(2)实现 handlerMatch线程安全忙等问题 处理开始匹配/停止匹配请求 实现 handleTestMessage 先从会话中拿到当前玩家的信息解析客户端发来的请求判定请求的类型 如果是 startMatch&…

11.spark源码编译

1.构建环境 构建环境&#xff1a; ubuntu 22.04 jdk 11 scala 2.12 maven 3.9 spark 3.5 2.构建 获取代码 pull代码后&#xff0c;切换到对应分支。 git checkout branch-3.5编译 构建spark mvn -DskipTests clean package \-Dhadoop.version3.3.6 \-Phive -Phive-thrif…

前端必备——Grid布局详解

Grid布局&#xff0c;又称为CSS网格布局&#xff0c;是W3C提出的一个二维布局系统&#xff0c;它允许开发者以行和列的形式来布局网页内容。以下是Grid布局属性的详细解析&#xff1a; 一、容器属性 display grid&#xff1a;将元素设置为块级网格容器。inline-grid&#xff1…

基于Java Web和SSM框架的硕士研究生招生考试系统开发

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;本项目旨在构建一个硕士研究生招生考试专业报考查询及学习系统&#xff0c;使用Java Web技术并集成了Spring、SpringMVC和MyBatis&#xff08;SSM&#xff09;框架。系统通过模块化架构和分离关注点&#xff08…

MCP Web Research Server 安装与配置指南

MCP Web Research Server 安装与配置指南 mcp-webresearch MCP web research server (give Claude real-time info from the web) 项目地址: https://gitcode.com/gh_mirrors/mcpw/mcp-webresearch 1. 项目基础介绍 MCP Web Research Server 是一个基于 Model Context …

0基础入门前端到精通(一)

目录 一丶前端开发介绍 1. 网页的组成部分 2. 网页的本质是什么&#xff1f; 3. 前端代码如何变成网页&#xff1f; 4. 统一网页显示标准&#xff1a;Web 标准 二丶HTML & CSS 1. 什么是 HTML&#xff1f; 2. 什么是 CSS&#xff1f; ​3. HTML 快速入门&#xff0…

一文了解Blob文件格式,前端必备技能之一

文章目录 前言一、什么是Blob&#xff1f;二、Blob的基本特性三、Blob的构造函数四、常见使用场景1. 文件下载2. 图片预览3. 大文件分片上传 四、Blob与其他API的关系1. File API2. FileReader3. URL.createObjectURL()4. Response 五、性能与内存管理六、实际案例&#xff1a;…

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

免责声明&#xff1a;用户因使用公众号内容而产生的任何行为和后果&#xff0c;由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任 **本文以攻防世界部分题为例进行演示&#xff0c;后续会对攻防世界大部分的web题目进行演示&#xff0c;如果你感兴趣请…

解决 Android WebView 无法加载 H5 页面常见问题的实用指南

目录 1. WebView 简介 2. 常见问题 3. 网络权限设置 4. 启用 JavaScript 5. DOM Storage 的重要性 6. 处理 HTTPS 问题 7. 设置 WebViewClient 8. 调试工具 9. 其他调试技巧 10. 结论 相关推荐 1. WebView 简介 Android WebView 是一种视图组件&#xff0c;使得 And…