SELECT 的查询优化方案有哪些?

进阶数据库系列(二十三):PostgreSQL 性能优化 PostgreSQL优化一方面是找出系统的瓶颈,提高PostgreSQL数据库整体的性能; 另一方面,需要合理的结构设计和参数调整,以提高用户操作响应的速度; 同时还要尽可能的节省系统资源,以便系统可以提供更大负荷的服务。 阅读详情

在实际 Java 项目开发中,PostgreSQL 的 SELECT 查询性能直接影响接口响应速度和数据库负载。即使 SQL 能查出正确结果,如果执行缓慢,依然会拖垮系统。

下面我将为你系统梳理 PostgreSQL SELECT 查询的常见优化方案,结合 真实开发场景 + 可落地的 SQL 示例 + 中文注释说明,帮助你写出高效、稳定的查询。


🚀 一、PostgreSQL SELECT 查询优化核心策略

优化方向目标
✅ 索引优化避免全表扫描,提升查询速度
✅ SQL 重写改写低效 SQL,利用数据库优势
✅ 执行计划分析定位性能瓶颈
✅ 分页优化避免深度分页慢
✅ 统计信息更新帮助优化器生成更好执行计划
✅ 表结构设计从源头避免性能问题

✅ 二、优化方案与示例(含中文注释)

🔧 1. 【索引优化】为高频查询字段创建索引

❌ 问题:没有索引导致全表扫描
-- 查询订单(无索引时会 Seq Scan 全表扫描)
SELECT * FROM orders WHERE user_id = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11';
✅ 优化:创建 B-tree 索引
-- 为 user_id 创建索引(高频查询字段)
CREATE INDEX idx_orders_user_id ON orders(user_id);

-- 如果按状态 + 时间查询,创建复合索引
CREATE INDEX idx_orders_status_created ON orders(status, created_at DESC);

✅ 效果:Index Scan 替代 Seq Scan,查询从秒级降到毫秒级。


🔧 2. 【索引优化】为 JSONB 字段创建 GIN 索引

❌ 问题:JSONB 查询慢
-- 查询 profile 中昵称为 "张三" 的用户
SELECT * FROM users WHERE profile->>'nick' = '张三';
-- 无索引时极慢
✅ 优化:创建 GIN 索引
-- 为 JSONB 字段创建 GIN 索引,加速查询
CREATE INDEX idx_users_profile_gin ON users USING GIN (profile);

-- 或为特定字段创建表达式索引(更高效)
CREATE INDEX idx_users_nick ON users((profile->>'nick'));

✅ 适用场景:用户扩展属性、配置项、动态表单等。


🔧 3. 【SQL 重写】避免在 WHERE 中使用函数(破坏索引)

❌ 问题:函数包裹字段导致索引失效
-- ❌ 错误:DATE() 函数导致 created_at 索引无法使用
SELECT * FROM orders 
WHERE DATE(created_at) = '2024-06-01';
-- 执行计划:Seq Scan(全表扫描)
✅ 优化:改用范围查询
-- ✅ 正确:使用范围,可走索引
SELECT * FROM orders 
WHERE created_at >= '2024-06-01 00:00:00'
  AND created_at < '2024-06-02 00:00:00';

✅ 效果:Index Scan 成功使用 idx_orders_created_at。


🔧 4. 【分页优化】避免深度 OFFSET 分页

❌ 问题:OFFSET 越大越慢
-- ❌ 深度分页:跳过 50,000 条数据,性能极差
SELECT id, title FROM articles ORDER BY created_at DESC LIMIT 10 OFFSET 50000;
✅ 优化:使用游标分页(Cursor-based Pagination)
-- ✅ 游标分页:基于上一页最后一条的 created_at
SELECT id, title, created_at 
FROM articles 
WHERE created_at < '2024-06-01 10:00:00'  -- 上一页最后一条的 created_at
ORDER BY created_at DESC 
LIMIT 10;

✅ 优势:始终使用索引,性能稳定,适合大数据量场景。


🔧 5. 【执行计划分析】使用 EXPLAIN ANALYZE 定位瓶颈

-- 分析慢查询的执行计划
EXPLAIN ANALYZE 
SELECT u.username, COUNT(o.id) 
FROM users u 
LEFT JOIN orders o ON u.id = o.user_id 
GROUP BY u.id 
ORDER BY COUNT(o.id) DESC 
LIMIT 10;
🔍 关注输出:
  • Seq Scan → 是否应为 Index Scan?
  • Nested Loop / Hash Join → 成本是否过高?
  • Buffers → 是否大量磁盘读取?

✅ 建议:在 DataGrip 中开启 “Auto Explain” 功能,自动分析。


🔧 6. 【复合索引优化】按查询顺序创建复合索引

❌ 问题:索引顺序错误
-- 查询条件:status = 'paid' AND created_at > ?
-- 但索引是 (created_at, status) → 无法高效使用
✅ 优化:调整索引顺序
-- ✅ 正确:等值条件在前,范围在后
CREATE INDEX idx_orders_paid_recent ON orders(status, created_at DESC);

✅ 原则:

  • 等值查询字段放前面(status = 'paid')
  • 范围查询字段放后面(created_at > ?)

🔧 7. 【避免 SELECT *】只查需要的字段

❌ 问题:传输大量无用数据
-- ❌ 查了 password_hash、profile 等不需要的字段
SELECT * FROM users WHERE username = 'zhangsan';
✅ 优化:明确指定字段
-- ✅ 只查接口需要的字段
SELECT id, username, email, created_at 
FROM users 
WHERE username = 'zhangsan';

✅ 效果:

  • 减少网络传输
  • 避免敏感字段泄露
  • 提升缓存效率

🔧 8. 【统计信息更新】让优化器做出更好决策

-- 手动更新表的统计信息(帮助查询优化器选择更优执行计划)
ANALYZE users;
ANALYZE orders;

-- 或定期自动执行(通常 PostgreSQL 自动做,但大表可手动触发)

✅ 适用场景:大表数据批量导入后,或发现执行计划突然变差。


🔧 9. 【分区表】大数据量表按时间分区

-- 创建按月分区的订单表(适合日志、订单等大表)
CREATE TABLE orders (
    id SERIAL,
    user_id UUID,
    amount DECIMAL(10,2),
    created_at TIMESTAMP NOT NULL
) PARTITION BY RANGE (created_at);

-- 创建分区
CREATE TABLE orders_2024_06 PARTITION OF orders
    FOR VALUES FROM ('2024-06-01') TO ('2024-07-01');

CREATE TABLE orders_2024_07 PARTITION OF orders
    FOR VALUES FROM ('2024-07-01') TO ('2024-08-01');

✅ 效果:查询某月数据时,只扫描对应分区,极大提升性能。


🔧 10. 【物化视图】预计算复杂查询结果

-- 创建物化视图:用户订单统计(避免每次实时计算)
CREATE MATERIALIZED VIEW user_order_stats AS
SELECT 
    user_id,
    COUNT(*) AS order_count,
    SUM(amount) AS total_amount
FROM orders 
WHERE status = 'paid'
GROUP BY user_id;

-- 刷新数据(可定时任务执行)
REFRESH MATERIALIZED VIEW user_order_stats;

✅ 适用场景:报表、后台统计页面,数据不要求实时。


📊 三、优化前后对比示例

优化前优化后效果
SELECT * FROM orders WHERE user_id = ?(无索引)创建 idx_orders_user_id从 1.2s → 10ms
OFFSET 10000 LIMIT 10改为游标分页从 800ms → 15ms
WHERE DATE(created_at) = ?改为范围查询从 Seq Scan → Index Scan
N+1 查询改为 JOIN FETCH101 次 → 1 次 SQL

✅ 四、推荐优化流程(Java 开发者可用)

1. 开启 SQL 日志(application.yml)
2. 发现慢接口 → 查日志定位 SQL
3. 用 EXPLAIN ANALYZE 分析执行计划
4. 检查是否缺少索引、是否 N+1、是否深度分页
5. 添加索引 / 重写 SQL / 改用游标分页
6. 验证性能提升
7. 提交代码 + 注释优化原因

🎁 五、附加建议

建议说明
✅ 使用 pg_stat_statements 监控最耗时 SQLCREATE EXTENSION pg_stat_statements;
✅ 生产环境避免 LIKE '%xxx%'改用 pg_trgm + GIN 索引支持模糊查询
✅ 大表避免 COUNT(*)改用近似统计或物化视图
✅ 定期 VACUUM ANALYZE清理死元组,更新统计信息
深入解析数据查询操作:SELECT 语句的使用与应用 title: 深入解析数据查询操作:SELECT 语句的使用与应用author:excerpt:数据查询是数据库操作中最频繁、最重要的一部分。无论是开发应用程序、进行数据分析,还是维护数据库,熟练使用 SELECT 语句都是必不可少的技能。本文将系统地讲解 PostgreSQL 中的 SELECT 语句,包括基本查询、条件查询以及如何利用 ORDER BY 和 LIMIT 进行排序与限制展示的数据量。扫描在关系型数据库管理系统中,数据查询(SELECT)是与数据交互的核心操作之一。 阅读详情

相关推荐

大表查询的优化方案

大表查询的优化方案

Spring_Lws的博客 558

深度剖析PostgreSQL慢SQL:原因与优化方案大揭秘

PostgreSQL是一款强大的关系型数据库,但在实际使用过程中,许多用户经常会遇到慢SQL的问题。这些问题不仅会降低数据库性能,还会直接影响业务流程和用户体验。因此,本文将会深入分析PostgreSQL慢SQL的原因和优化方案,帮助用户更好地利用这个优秀的数据库系统。无论你是初学者还是专业开发者,本文都将为你提供实用的技巧和方法,让你的PostgreSQL数据库始终保持高效快速。

洛阳泰山的博客 1万+

【AutoSar CP】SoAd模块

比如对于特定的PDU,其PduId在程序编译时就确定了,但是在代码运行中,该PduId可能需要发送到不同的远端ip,这时就需要用SoAd来设置连接远端地址信息。SoAdSocketConnectionGroup(连接参数)SoAdSocketRoute(接收数据)SoAdRoutingGroup(开关)SoAdPduRoute(发送数据)

至道无难,唯嫌拣择。 1684

PostgreSQL查询优化:让你的SQL查询更高效

在数据库应用中,查询是一项频繁的操作。查询优化旨在通过调整数据库查询语句和索引设计,提高查询性能,减少响应时间,从而使系统更加高效运行。对于特定的数据类型和查询需求,可以考虑创建自定义索引。这需要实现相应的操作符和查询支持。-- 示例:在自定义类型上创建GiST索引。

竹林幽深 2280

地图可视化类型大全

地图可视化类型大全: 散点地图 网格地图 聚合地图 气泡地图 热力图 Choropleth地图/分级设色地图/分级区域地图/着色地图/分级统计地图(百度百科这样翻译)/等值域地图/分段设色地图 Cartogram地图/变形地图/示意地图 规则形状地图 /RecMap/Demers Cartogram/瓷砖网格地图/DorlingMap 流型图(Flow Map)\流线图\流向图\轨迹地图 复合地图

codeuniverse的博客 3532

STM32MP157+AD7606BSTZ四通道IEPE传感器采集方案实战(附完整电路图)

本文详细介绍了基于STM32MP157和AD7606BSTZ的四通道IEPE传感器采集方案,涵盖硬件电路设计、软件驱动开发及系统性能优化。通过精确的恒流源设计和同步采样技术,实现高精度振动信号采集,适用于工业振动监测等应用场景。

weixin_42713608的博客 700

PostgreSQL 查询优化——EXPLAIN应用

工作中有这个一个需求,开发反应search_history查询太慢了,看怎么优化一下。 data=> \timing 启用计时功能. data=> SELECT * data-> FROM data-> ( data(> SELECT s.org_id,user_id,id_no,MIN (s.create_date) AS create_date,T.corp_type AS TYPE

nayanminxing的专栏 1万+

从SAR信号到洪涝地图:基于Sentinel-1数据的水体快速提取实战

本文详细介绍了如何利用Sentinel-1 SAR数据快速提取水体信息并生成洪涝地图的实战方法。通过预处理五部曲和SDWI指数计算,结合具体案例展示了SAR技术在洪涝灾害应急监测中的高效性和准确性,为救援决策提供关键支持。

weixin_29201313的博客 461

深入了解PostgreSQL:高级查询和性能优化技巧

本文将深入探讨POSTGRESQL的高级查询和性能优化技巧,帮助您最大程度地发挥这个强大数据库的潜力。

PGCCC的博客 2807

深度学习的unfold操作

对于彩色图像这样的三维数据,unfold操作会对每个通道分别进行上述的二维展开操作。例如,一个 RGB 图像,在对其进行unfold操作时,红色通道、绿色通道和蓝色通道的数据都会被独立地按照定义的窗口和步长展开,然后将这些展开后的通道数据按照原来的通道顺序组合在一起,形成新的张量。与我们熟悉的卷积类似,unfold也是使用一个特定大小的窗口和步长自左至右、自上至下滑动,不同的是,卷是滑动后与核求乘积(所以取名为卷积),而unfold滑动后不求乘积,是将窗口内的数据展开。

xulibo5828的博客 2163

C#与大数据分析:如何通过上位机进行设备故障诊断与预测

设备故障诊断是通过对设备的运行状态数据进行分析,识别和确认故障的类型和位置。而设备故障预测则是通过对设备的历史数据和运行状态进行分析,预测设备何时可能出现故障,从而进行预防性维护。数据采集:通过各种传感器、PLC、嵌入式设备等采集设备运行数据,如温度、压力、振动、转速、功率等。数据预处理:对采集到的数据进行清洗、去噪、缺失值处理、标准化等操作,以确保数据质量。特征工程:从原始数据中提取出有助于故障诊断和预测的特征,例如统计特征、时域特征、频域特征等。数据分析与建模。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1060

mysql select查询语句优化方案

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。  2.应尽量避免在 where 子句中使用!=或 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:  select id from t where num is null  可以在num上设置默认值0,

天上的海风博客 1083

Ubuntu系统等保3级配置核查与加固

虽然这种方法在某些老旧的系统中仍然有效,但现代Linux发行版通常不推荐使用hosts.deny和hosts.allow文件来管理防火墙规则,因为它们的功能已经被更现代的防火墙管理工具(如iptables或firewalld)所取代。如果你想禁止特定的环境变量,可以从这个列表中移除它们,或者如果你想完全阻止所有环境变量的传递,可以将其设置为空。你可以通过ssh-keygen生成密钥对,并将公钥添加到用户的~/.ssh/authorized_keys文件中。修改配置后,需要重启SSH服务以使更改生效。

悦分享 183

再见了 SELECT *! MySQL 查询优化方案,确实牛逼!

前两天看到字节一个老哥写的帖子,提到高阶开发者必须掌握的技能,其中他明确提出了“精通MySQL”。为啥MySQL对开发人员如此重要?第一,不管你去面试哪家公司,数据库是必问项,而MySQL...

路人甲Java 391

【Claude】Auto mode cannot determine the safety of an action 报错已解决

Claude Code Auto mode 安全分类器报错完整解析,涵盖 temporarily unavailable、could not evaluate、transcript exceeded 三种情况的根因与处理

博客 9945

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

再见了 SELECT *!大厂的 MySQL 查询优化方案,确实牛逼!

前两天看到字节一个老哥写的帖子,提到高阶开发者必须掌握的技能,其中他明确提出了“精通MySQL”。为啥MySQL对开发人员如此重要?第一,不管你去面试哪家公司,数据库是必问项,而MySQL...

weixin_43167418的博客 144

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

SELECT‘MySQL索引优化实战从慢查询到高性能的完整解决方案‘AS文章标题;

MySQL索引优化是一个系统工程,需要深入理解索引原理,掌握诊断工具的使用,并结合实际业务场景制定优化策略。从识别慢查询开始,通过EXPLAIN分析执行计划,合理设计索引,应用覆盖索引、索引下推等高级技巧,可以显著提升查询性能。记住,索引不是越多越好,每个索引都会增加写操作的开销,因此需要在读写性能之间找到平衡点。持续的监控、分析和优化是保持数据库高性能的关键。

sdwsd的专栏 396

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

mysql in select 效率_MYSQL的in条件查询其效率怎么样,有没有好的查询优化方案?(具体的使用场景在里面叙述了)...

在我的APP中,有一个类似于威信朋友圈那样的功能。就是能查看好友的分享。具体的sql语句大概就是:select photo.* from photo where userId in(1,2,3,.........)in条件里面就是我的好友。这是提前查询出来的。这里有一个迷惑,就是假设我的好友有1000个,会不会查询的效率就慢了呢?我不知道那些开源的PHP SNS是咋做的。。各位大神应...

weixin_42613572的博客 1013

mysql不要使用select_查询语句不使用 SELECT * 的八个原因

PPT:郑州QQ 视频:郑州视频1.背景介绍(1)数据库起源于 20 世经 90 年代,当时美国为了战争的需要,把各种情报收集在一起,存储隐藏在计算机内,叫做 Data Base(DB)。(2)SQL语句用于访问和处理数据库的标准的计算机语言,简称 结构化查询语言。(3)SELECT 语句用于从表中选取数据,结果被存储在一个结果表中(称为结果集)。2.知识剖析select语句的常用写法:SELEC...

weixin_34221374的博客 1757

mysql select IN优化

MySQL SELECT IN优化指南 作为一名经验丰富的开发者,我深知在处理大数据量时,优化SQL查询的重要性。今天,我将向刚入行的小白们介绍如何优化SELECT IN语句,以提高查询效率。 流程概述 首先,让我们通过一个表格来概述整个优化流程: 步骤 描述 1 确定查询需求 2 编写原始SELECT ...

weixin_42029848的博客 395

SQL优化 之 查询语句优化详解

没有放之四海皆准的优化规则,实际效果需要通过测试验证,不同数据库版本和不同数据量级可能有不同的最优方案。

u013334925的博客 1029

Django `select_related` 查询优化

本文介绍了Django ORM中的N+1查询问题及其解决方案。当通过外键访问关联对象时,未优化的查询会导致执行N+1次数据库查询,严重影响性能。使用select_related可以通过JOIN操作一次性获取关联数据,将查询次数优化为1次。文章详细讲解了select_related的基本用法、深度关联查询(使用双下划线语法)以及查看生成SQL的方法,并提供了最佳实践建议:仅当确实需要访问关联对象字段时才使用select_related,避免过度使用和深度关联导致性能下降。最后通过对比表总结了普通查询与优化查询

言之。 1万+
上一篇: SELECT 查询推荐做法总结
下一篇: JDK 常用的原生注解详解
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值