首页 游戏 软件 资讯 排行榜 专题
首页
业界动态
MySQL 8.0 LATERAL 子查询优化实战 3秒慢查询提速至0.8秒全记录

MySQL 8.0 LATERAL 子查询优化实战 3秒慢查询提速至0.8秒全记录

热心网友
13
转载
2026-05-14

今天我们来深入探讨一个MySQL慢查询优化的实战案例。一个看似常规的查询,平均执行时间却高达2秒,在一小时内被执行了超过700次,这个性能瓶颈必须得到解决。经过优化,执行时间从3秒大幅降低至约0.8秒,效果非常显著。整个优化过程的核心思路可以总结为下图:

免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈

SQL优化:从3秒到0.8秒

一、问题定位与深度分析

监控系统明确地指出了问题所在:一个查询在过去一小时内的执行次数超过700次,平均耗时达到2秒。下图展示了慢查询的监控概览:

慢查询监控截图

引发问题的SQL语句如下:

SELECT overdue_amount
FROM cont_execute exe
LEFT JOIN (
  SELECT
    cont_number,
    is_important_cont,
    is_important_cont_in,
    ROW_NUMBER() OVER (
      PARTITION BY cont_number
      ORDER BY create_time DESC
    ) AS rn
  FROM cont_review_main
  WHERE del_flag = 0
) main
ON exe.cont_number = main.cont_number
WHERE exe.del_flag = 0
  AND main.rn = 1
  AND main.is_important_cont_in = 0
  AND exe.cont_company_name = 'xx科技有限公司'

值得注意的是,当时监控工具给出的常规优化建议,例如删除冗余索引或简单改写SQL,均未能有效提升性能。这表明问题的根源可能更为深层。

监控工具建议截图

1.1 执行计划深度剖析

要找到根本原因,必须分析SQL的执行计划。下图是优化前的执行计划详情:

执行计划分析截图

通过执行计划,我们识别出了两个核心的性能瓶颈。

1.2 核心瓶颈识别

第一个瓶颈:派生表缺乏索引,导致全表扫描。
子查询生成的派生表,MySQL无法为其自动创建索引(除非使用LATERAL或物化视图技术)。因此,过滤条件main.rn = 1实际上是在一个没有索引的派生表上进行的全表扫描,这次扫描涉及高达77,724行数据。

第二个瓶颈:cont_review_main表的filesort操作开销巨大。
尽管查询使用了idx_htps1_main索引(基于del_flag字段),但窗口函数中的PARTITION BY cont_number ORDER BY create_time DESC子句,需要对这77,724行数据执行一次额外的排序操作,即Using filesort,这个过程消耗了大量CPU和内存资源。

二、优化方案与具体实施

针对上述瓶颈,一个高效的优化策略是使用LATERAL关联子查询。

2.1 采用LATERAL关联子查询

将原始SQL改写为如下形式(要求MySQL版本在8.0.14及以上):

SELECT exe.overdue_amount
FROM cont_execute exe
INNER JOIN LATERAL (
  SELECT
    is_important_cont,
    is_important_cont_in
  FROM cont_review_main main
  WHERE main.cont_number = exe.cont_number
    AND main.del_flag = 0
  ORDER BY main.create_time DESC
  LIMIT 1
) main
ON main.is_important_cont_in = 0
WHERE exe.del_flag = 0
  AND exe.cont_company_name = '伟仕佳杰(重庆)科技有限公司';

这种写法的优势是什么?
关键在于LATERAL关键字。它允许子查询引用外层查询(exe)当前行的列值(此处是exe.cont_number)。这意味着,对于cont_execute表中的每一行,子查询都能利用cont_number进行高效过滤,直接获取对应合约的最新一条审核记录,从而彻底避免了生成庞大的中间派生表并进行全表扫描。

配套的索引优化建议:
为了进一步提升子查询中排序操作的效率,建议在cont_review_main表上创建如下复合索引:

CREATE INDEX idx_main_cont_time ON cont_review_main(cont_number, create_time DESC, del_flag);

优化效果立竿见影。在约3万条测试数据的环境下,查询执行时间从原来的约3秒下降到了0.75秒

优化后执行时间截图

三、深入理解LATERAL关键字

LATERAL是MySQL 8.0.14版本引入的关键字,可以理解为“横向关联”或“逐行引用”。它打破了一个传统限制:普通子查询是独立执行的,而LATERAL子查询可以引用其外部查询中当前行的列值。

简单来说,普通子查询是“闭门造车”,LATERAL子查询则是“协同作战”。

3.1 普通子查询与LATERAL子查询对比

普通子查询(错误示例):
下面的写法会报错,因为子查询内部无法识别和引用外部表exe的字段。

-- 报错:Unknown column 'exe.cont_number' in 'where clause'
SELECT *
FROM cont_execute exe
INNER JOIN (
  SELECT *
  FROM cont_review_main m
  WHERE m.cont_number = exe.cont_number -- 这里exe不可见!
  LIMIT 1
) main

LATERAL子查询(正确示例):
使用LATERAL后,子查询就能“看到”并引用外部表的cont_number了。

-- 正确:LATERAL允许子查询引用exe的当前行
SELECT *
FROM cont_execute exe
INNER JOIN LATERAL (
  SELECT *
  FROM cont_review_main m
  WHERE m.cont_number = exe.cont_number -- 现在可以用了!
  ORDER BY m.create_time DESC
  LIMIT 1
) main

可以打一个形象的比方:普通子查询像是先做好一整桌菜(派生表)再端上来匹配;而LATERAL子查询更像是根据每位客人的口味(外部表的每一行),现场单独制作一道菜。

四、优化前后的逻辑对比与最佳实践建议

优化前后的两个SQL在业务逻辑上基本是等价的,但存在一个微妙的潜在差异,需要特别注意。

这个差异点在于:当cont_review_main表中,同一个cont_number存在多条create_time完全相同的记录时,两个SQL选择“最新记录”的结果可能不一致

  • 原SQL(使用ROW_NUMBER()): 在窗口函数排序时,如果create_time相同,数据库内部的排序是不确定的,可能导致每次选出的“rn=1”的行不同。
  • 优化后SQL(使用LIMIT 1): 同样,当ORDER BY create_time DESC遇到相同时间戳时,返回哪一行也是不确定的。

4.1 结论与最佳实践建议

create_time具有唯一性(或业务上不存在重复时间戳)的前提下,两个SQL完全等价。但如果存在重复时间,两者的结果都可能是不确定的,不应依赖这种不确定性。

最佳实践建议:
为了保证查询结果的绝对确定性,建议在排序条件中增加一个具有唯一性的列作为“决胜局”(tie-breaker)。例如,假设表有自增主键id,可以将两个SQL中的排序都修改为:

ORDER BY create_time DESC, id DESC

这样,即使创建时间相同,也会按照主键降序来明确选取一条记录,确保每次查询结果都严格一致。

来源:https://www.51cto.com/article/843209.html
免责声明: 游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

相关攻略

麒麟系统安装MySQL数据库详细配置教程
系统平台
麒麟系统安装MySQL数据库详细配置教程

在麒麟操作系统上安装MySQL时,常见问题源于架构不匹配、旧版本残留、依赖缺失或配置错误。针对银河麒麟V10,提供四种安装方法:APT包管理器适合桌面版快速部署;RPM手动安装需清理旧版本并按序安装组件;官方二进制包适用于离线或定制场景;Docker容器化便于快速验证与隔离测试。

热心网友
05.13
MySQL二进制日志恢复误删用户数据教程与mysqlbinlog解析指南
数据库
MySQL二进制日志恢复误删用户数据教程与mysqlbinlog解析指南

mysqlbinlog工具可将二进制日志解析为可读SQL,但不能直接恢复被删除的数据。恢复关键在于定位误删前的INSERT事件并手动将其转换为可执行的INSERT语句。操作时需确认日志为ROW格式,并注意处理GTID、会话变量等干扰信息。恢复后需检查时区、字符集及外键约束等潜在问题,确保数据准确。整个过程依赖人工判断与经验。

热心网友
05.11
MySQL登录延迟解决方案配置skip-name-resolve跳过DNS解析
数据库
MySQL登录延迟解决方案配置skip-name-resolve跳过DNS解析

MySQL登录延迟常因服务端反向DNS解析过慢。可通过在配置文件中添加skip-name-resolve并重启服务来解决。修改后需将授权表中的主机名更新为IP地址,否则相关账号会失效。客户端使用域名连接慢则属于正向解析问题,需另行处理。

热心网友
05.11
MySQL备份恢复后权限丢失的解决方案与系统库同步指南
数据库
MySQL备份恢复后权限丢失的解决方案与系统库同步指南

MySQL备份恢复后权限丢失,通常因备份时遗漏了mysql系统库。正确备份需显式包含mysql库,避免使用--all-databases参数。导入系统库备份需谨慎,可停止服务后以跳过权限检查模式启动并执行source命令。若无备份,可使用pt-show-grants工具从源库生成授权语句重建。需注意版本兼容性及主机名匹配等细节。

热心网友
05.11
MySQL安装后磁盘空间不足通用查询日志检查与清理方法
数据库
MySQL安装后磁盘空间不足通用查询日志检查与清理方法

MySQL安装后磁盘空间骤满,常因通用查询日志被意外开启并持续写入。通过命令检查日志状态,若开启则立即关闭并清空文件内容,而非直接删除。还须在配置文件中永久禁用该日志及慢查询日志,以防复发。此问题与二进制日志无关,需区分处理。

热心网友
05.11

最新APP

宝宝过生日
宝宝过生日
应用辅助 04-07
台球世界
台球世界
体育竞技 04-07
解绳子
解绳子
休闲益智 04-07
骑兵冲突
骑兵冲突
棋牌策略 04-07
三国真龙传
三国真龙传
角色扮演 04-07

热门推荐

清华大学AI视觉模型推理能力深度评测报告
AI
清华大学AI视觉模型推理能力深度评测报告

这项由清华大学、美团、香港大学等多家顶尖机构联合开展的研究,于2026年3月以预印本论文(arXiv:2603 25823v1)的形式发布。它直指当前AI视觉生成领域一个被长期忽视的核心问题:这些能画出“神作”的模型,到底有多“聪明”?研究团队为此构建了一套全新的测试基准——ViGoR-Bench,

热心网友
05.14
AI科学写作新突破:机器自动生成完整学术论文
AI
AI科学写作新突破:机器自动生成完整学术论文

人工智能的浪潮席卷了各个领域,机器在诸多任务上已展现出超越人类的能力。然而,有一个看似寻常却异常复杂的领域,始终是AI研究者们渴望攻克的堡垒——让机器像真正的学者那样,撰写出一篇结构严谨、逻辑自洽、图文并茂的完整科学论文。这远比下棋或识图要困难得多。 2026年3月,一项由中科院AgentAlpha

热心网友
05.14
法国Hornetsecurity与里尔大学合作:AI隐私保护技术从675亿到1.5亿参数的知识迁移实践
AI
法国Hornetsecurity与里尔大学合作:AI隐私保护技术从675亿到1.5亿参数的知识迁移实践

这项由法国Hornetsecurity公司与里尔大学、法国国家信息与自动化研究院(Inria)、法国国家科学研究中心(CNRS)以及里尔中央理工学院联合开展的研究,发表于2026年3月31日的计算机科学期刊,论文编号为arXiv:2603 29497v1。 在信息爆炸的今天,我们每天都在网上留下数字

热心网友
05.14
清华大学AI自主编写操作指南研究突破人工编程局限
AI
清华大学AI自主编写操作指南研究突破人工编程局限

当你满怀期待地拆开一台全新的智能设备,最令人困扰的往往不是如何使用它,而是如何让它真正“理解”指令并智能地执行任务。如今,一个更为优雅的解决方案可能已经出现。来自清华大学深圳国际研究生院与哈尔滨工业大学(深圳)的联合研究团队,近期取得了一项极具前瞻性的突破:他们成功训练人工智能自主“撰写”并精准理解

热心网友
05.14
华盛顿大学AI新突破图片转可编辑矢量图形技术详解
AI
华盛顿大学AI新突破图片转可编辑矢量图形技术详解

2026年3月,来自华盛顿大学、艾伦人工智能研究所和北卡罗来纳大学教堂山分校的研究团队,在图像智能矢量化领域取得了一项突破性进展。这项研究(论文编号:arXiv:2603 24575v1)开发了一个名为VFig的AI系统,它能够将静态的栅格图像智能地转换为可自由编辑的矢量图形,如同一位“图形考古学家

热心网友
05.14