PostgreSQL——SQL优化

PostgreSQL------SQL优化

    • 前言:信创下的PostgreSQL
    • [1. EXPLAIN下查看真正的执行结果](#1. EXPLAIN下查看真正的执行结果)
    • [2. 读取顺序](#2. 读取顺序)
    • [3. 核心指标分析](#3. 核心指标分析)
      • [3.1 读懂数值](#3.1 读懂数值)
      • [3.2 读懂扫描方式](#3.2 读懂扫描方式)
      • [3.3 读懂连接方式](#3.3 读懂连接方式)
      • [3.4 读懂I/O](#3.4 读懂I/O)
    • [4. 实战快速分析](#4. 实战快速分析)

前言:信创下的PostgreSQL

接触PostgreSQL数据库是所在项目为满足信创需求,将Oracle数据库迁移至PostgreSQL数据库。迁移过程中会伴随着SQL调整,相应的SQL会有慢查询的问题,因此记录一下PostgreSQL中SQL优化的流程。

1. EXPLAIN下查看真正的执行结果

sql 复制代码
##基础版
explain ...sql...

##进阶版
explain (analyze,verbose,buffers) ...sql...

进阶版增加了三个配置项,为了更详细地暴露具体问题,推荐三个配置项都加上

  • analyze:真正执行SQL
  • verbose:显示更多细节
  • buffers:显示内存、磁盘使用情况

2. 读取顺序

执行计划分析为树状结构,读取顺序如下:

  • 缩进最深优先执行;同级缩进下,由上至下执行。
  • 下层节点处理完成,传递给上层执行。

3. 核心指标分析

3.1 读懂数值

sql 复制代码
Seq Scan on users  (cost=0.00..15.00 rows=1000 width=36) (actual time=0.015..0.120 rows=1000 loops=1)

如上是某个SQL执行结果,其中数值部分为后半部分,具体如下:

  • cost:SQL优化器中的成本单位(注意:单位不是指 秒 )。

    示例中:

    • 0.00:启动成本,返回第一行数据需要准备的成本;0.00说明不需要准备。
    • 15.00:总成本,获取所有行数据预估需要的成本。
  • rows:优化核心数值,指的结果行数。

    示例中:

    • 1000:优化器预估返回行数。
    • actual-1000:真实执行后返回行数。
  • width:每行数据的平均字节数。select结果越多 ,则拉取的width值越大。

  • loops:当前节点被循环执行次数。当循环次数大于1时,总耗时=循环次数 × actual time。

  • time:真实执行成本时间。

3.2 读懂扫描方式

扫描方式 说明 注意点 优化思路
Seq Scan 全表扫描 仅适用小表;大表则会影响性能 1、查询条件增加过滤 2、数据表中增加索引
Index Scan 索引扫描。分两步: 1、查索引定位位置 2、根据位置回表查询 标准的查询 尝试利用覆盖索引(Covering Index)。
Index Only Scan 仅索引扫描。 与Index Scan相比不用回表查询,仅通过索引扫描就能够获取所需的数据。 极快 一般无需优化
Bitmap Heap Scan + Bitmap Index Scan 位图扫描。 先在索引中把符合条件的行标记为位图,然后批量取数。 一般 通常无需优化

3.3 读懂连接方式

连接方式 原理 场景 风险
Nested Loop (嵌套循环) 拿外表的一行,去内表找匹配的行 经典的小表驱动大表。 适用于:外表结果集为小表 外表的结果集决定内表查询,若外表结果集太大,会导致内表的查询非常慢
Hash Join (哈希连接) 把一张表的数据在内存中转Hash表,然后扫描另一张表进行连接。 大表之间的等值连接 数据库内存(work_mem)需要够大,否则性能会下降。
Merge Into (归并连接) 两表排列好顺序,然后类似拉链进行左右匹配。 连接字段上已经有索引(天生有序),或者数据量巨大且需要排序

3.4 读懂I/O

在开启BUFFERS后,会看到类似的输出:Buffers:shared hit=1274 read=311

这是最真实的性能指标:

  • shared hit:数据在内存中找到数据。
  • read:数据在内存中找不到数据,需要从磁盘进行读取。

尽一切可能减少 Buffers 的总数量(Hit + Read)。通常逻辑读(Hit)越少,SQL 就越快。如果 Read 很高,说明内存不够用或索引不佳。

4. 实战快速分析

实战分析步骤:

  • 1、查看哪个actual time值最高,说明该查询耗时最高。(注意 actual time × loops)
  • 2、估算偏差:查看rows和actual偏差是否过大,超过10倍以上则先对涉及的表进行ANALYZE tableName(PG内部的地图可能没有及时更新, 需要使用语句更新)
  • 3、扫描类型:首先避免大表的Seq Scan,如果Index Scan还是慢,则考虑添加索引,以满足索引覆盖。
  • 4、I/O查看:查看Buffers的read是否过高,是否出现Temp Read/Write。
  • 5、Filter:如果节点显示 Filter:(col_a =5)且同时出现Rows Removed by Filter,说明没走索引,在内存中硬过滤。
相关推荐
这个DBA有点耶8 小时前
连拿六年第一后宣布出海:国产数据库凭什么敢撕掉“平替”的标签?
数据库·人工智能·架构
云和恩墨9 小时前
数据库监控简史:从会回答到能交付——AI-DBA如何成为真正的数字同事
数据库·人工智能·dba
这个DBA有点耶9 小时前
为什么删掉索引后,查询瞬间变快了?探讨MySQL的随机I/O与顺序I/O博弈
数据库·mysql·代码规范
kingx310 小时前
BugKu 渗透测试 4 实战:文件上传打点,5 Flag 全通
数据库·渗透测试·web·内网渗透
我命由我1234510 小时前
Python 实用操作 - 文件操作(打开与关闭文件、读取文件、文件写入)
java·开发语言·前端·javascript·数据库·python·java-ee
SelectDB11 小时前
Apache Doris 与 SelectDB 是什么关系?从开源技术到面向 Agent 的极速分析数据库
大数据·数据库·数据分析
VimorphTech11 小时前
文本已经改了,旧的音频生成结果还能回写吗?
java·数据库·mybatis
SelectDB11 小时前
存算分离冷查询提速 7.5 倍!Apache Doris 4.2 Peer Read 实现跨计算组缓存复用
大数据·数据库·数据分析
盛世宏博智慧档案11 小时前
一站式智慧档案解决方案,如何实现防火防盗漏水多维度安全监测实践
服务器·网络·数据库
数据库小学妹11 小时前
MySQL磁盘IO瓶颈:iostat与刷脏fsync
数据库·mysql·性能优化