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

PostgreSQL慢SQL优化分享

SQL优化的核心在于如何正确读懂执行计划,充分了解SQL慢的具体原因,并根据执行计划让优化器选择合适的扫描方式、连接方式、合理利用索引,减少无效数据扫描。


一、什么是执行计划

大白话解释:写的SQL是 “需求”(比如 :查询 user 中 id=100 的用户信息),而执行计划就是数据库经过计算给出的具体 “实施方案”。它会根据数据库库表索引等的实际情况判断:通过哪种方式(是直接扫描整个用户表,还是通过索引快速定位到目标行)获取数据更快,更节省资源,从而为用户提供最优的方案。
虽然数据库优化器会提供最优的计划,但偶尔也会因统计信息过时、索引不合理等情况,产生 “低效计划”,这就是我们需要分析执行计划的核心原因。

核心结论:看懂执行计划,就能搞清楚SQL执行的执行情况,找到SQL慢的“根因”,从而有针对性地对进行优化。


二、如何获取执行计划

  • EXPLAIN + SQL: 查看预估执行计划,不实际执行SQL,只返回优化器预估的执行计划,速度快,适合快速排查SQL的执行逻辑。
  • EXPLAIN ANALYZE + SQL:实际执行计划,不仅输出执行计划,还会实际执行SQL,返回真实的扫描行数、执行时间、循环次数等。

:生产环境注意避免执行EXPLAIN ANALYZE,避免复杂耗时SQL对生产环境数据库产生性能影响,可先在测试环境复现。


三、执行计划解析

树形结构与执行顺序

执行计划为自底向上执行的树形结构

  • 叶子节点:缩进最深、最底层
  • 中间节点:缩进介于两者之间
  • 根节点:无缩进、最顶层

执行顺序

  • 缩进越多 → 层级越深 → 越靠近叶子节点(先执行);缩进越少 → 层级越浅 → 越靠近根节点(后执行
  • 当多个叶子节点缩进层级相同(属于同一父节点的子节点)时,执行顺序遵循“左到右 / 上到下”的核心规则

核心指标名词解释

  • cost0.00..100.00):..前是 “启动成本”(返回第一行的成本),..后是 “总的执行成本”,(数值越小,效率越高)
  • rows:预估行数,可与 EXPLAIN ANALYZE 中的 actual rows 对比,若差值过大,说明统计信息不准确。
  • width:字节数,预估当前返回每行的数据字节大小,值越大,内存和IO开销越高。

EXPLAIN ANALYZE 专属字段

  • actual time0.00..100.00): 实际启动时间…实际执行时间
  • actual rows: 实际行数,行数过大,可优化过滤条件,减少后续数据处理压力
  • loops:循环次数(嵌套循环会多次执行)

扫描类型解析

执行计划的扫描类型是优化器基于成本(IO成本、CPU成本)选择的最优方案,优化器会计算每种扫描方式的成本,优先选择成本最低的扫描方案。

扫描方式是执行计划中的核心部分,直接决定SQL语句的执行速度,以下为四种常见的扫描方式

1.Seq Scan:全表扫描,多数情况下效率最低,也是SQL优化的重点排查方向

名词解释

  • Filter: 行级过滤条件
  • Rows Removed by Filter: 被 Filter 条件过滤掉的行数

触发条件

  • 查询选择性低(返回行数/表总行数 > 20%~30%),优化器认为走索引的随机 IO 成本 > 全表顺序 IO 成本
  • 表数据量极小
  • 查询条件没有索引
  • 表的统计信息不准确,优化器无法获取准确的返回行数
  • 索引失效(如字段有隐式类型转换)

性能特点

  • 优点:顺序IO,磁盘效率高,不需要扫描索引+回表操作
  • 缺点:扫描所有记录,表数据量大时,过滤条件复杂时,CPU和IO开销极高

样例

-- 查询sqlSELECT*FROMusersWHEREage>10;-- explainSeq Scanonusers(cost=0.00..19424.00rows=990000width=100)(actualtime=0.02..200.10rows=990000loops=1)Filter:(age>10)-- 过滤条件:只保留age>10的行RowsRemovedbyFilter:10000-- 被过滤的行数
2.Index Scan:索引扫描(先遍历索引,再回表读取行数据),多数情况下效率高

名词解释

  • Index Cond: 索引筛选条件
  • Filter:回表过滤条件

触发条件

  • 查询选择性高,优化器认为随机IO的成本 < 全表/位图扫描
  • 查询条件存在匹配的有效索引
  • 优化器计算索引扫描的成本最低。

性能特点

  • 优点:过滤条件在索引扫描时完成,无全表扫描,CPU/IO 开销低
  • 缺点:表中的数据的物理位置是无序的,索引扫描会根据索引键频繁 “随机访问” 数据表,磁盘随机IO成本高

样例

-- sqlEXPLAINANALYZESELECT*FROMusersWHEREage=88;-- explainIndexScanusingidx_users_ageonusers(cost=0.43..8.45rows=10width=100)(actualtime
http://www.cnnetsun.cn/news/1764290.html

相关文章:

  • 紧急预警:Python 3.13即将移除C API部分旧接口,Mojo 2026 LTS版已成唯一合规混合方案(迁移窗口仅剩112天)
  • 批量爬取小说章节并优化排版(附完整可运行脚本)
  • C语言完美演绎7-7
  • OpenClaw技能开发:为Kimi-VL-A3B-Thinking定制商品识别模块
  • 中文技术博客】基于STM32的BMS电池管理系统 | LTC6804和LTC3300实现SOC...
  • 远程办公时代,软件测试从业者如何构筑不可替代性
  • 高效网盘直链解析工具:告别限速,一键获取高速下载地址
  • STM32磁悬浮控制板(二)硬件架构与接口设计详解
  • 终极跨平台AirPods体验增强方案:在Windows和Linux上解锁完整功能
  • 超越 DOE 菜单:最优设计和 OMARS 设计
  • 神经网络基础:从感知机到多层感知机(MLP)
  • STK航空仿真(五):坐标系转换实战与飞行姿态解算
  • 艾尔登法环存档迁移专家:保障游戏进度安全流转的技术方案
  • Neko疑难排解大全:常见问题与解决方案清单
  • 性能测试相关概念
  • 离散数学等价关系证明实战:从定义到解题技巧全解析
  • Qwen2.5-14B-Instruct应用场景:像素剧本圣殿为播客创作者自动生成对话脚本
  • 敏捷教练的测试工具箱:协作与质量并重
  • Oracle DBA 效率提升的秘密:批量部署环境再也不头疼!
  • 【AI原生开发实战】1.2 传统开发 vs AI原生开发:思维转变与架构差异
  • 行李箱密码锁怎么设置?3 类常见锁型通用教程 + 安全避坑指南
  • Dynamic Focus in Bounding Box Regression: How Wise-IoU Optimizes Anchor Box Learning
  • wscat 高级功能详解:SSL 证书、代理和认证配置实战
  • 从‘上不了百度’到搞懂DNS:一次真实的网络故障如何带我入门计算机网络
  • NaV1.8抑制剂苏泽曲林的理化性质与制备方法
  • 别再只用ARIMA了!用PyTorch手把手教你搭建N-BEATS模型预测销量(附完整代码)
  • Linux 线程:从虚拟地址空间到 POSIX 线程控制全解析
  • 抖音无水印视频批量下载终极指南:从零搭建高效内容获取工作流
  • Unity游戏翻译完整指南:让语言不再成为游戏障碍
  • Carsim-Simulink联合仿真MPC主动悬架 MPC是一种根据模型预测的方式在有限时域内求解最优解的控制方法,