SELECT 查询推荐做法总结

查询数据:SELECT语句详解 查询数据:SELECT语句详解 1.背景介绍 在关系数据库管理系统(RDBMS)中,SELECT语句是最常用和最重要的SQL语句之一。它用于从一个或多个表中检索数据。无论是简单的查询还是复杂的查询,SELECT语句都是实现数据查询的核心工具。 数据查询是数据库应用程序中不可或缺的 阅读详情

在真实的 Java 项目开发过程中,SELECT 查询的写法不仅影响接口性能,还直接关系到系统的可维护性、可扩展性和数据库负载。作为后端开发者,我们不能只是“能查出数据就行”,而应遵循最佳实践,写出高效、安全、可读性强的 SQL。

以下是我在多个企业级项目(包括电商、金融、SaaS 平台)中总结出的 PostgreSQL SELECT 命令推荐做法与建议,每一条都附有 原因说明和实际影响。


✅ 一、推荐做法与建议(含原因)

1. ❌ 避免使用 SELECT *,明确指定字段

-- ❌ 不推荐
SELECT * FROM users;

-- ✅ 推荐
SELECT id, username, email, created_at FROM users;

原因:

  • 性能更好:减少网络传输和内存占用,尤其当表有 TEXT、JSONB、BYTEA 大字段时。
  • 可维护性强:接口返回字段清晰,避免因表结构变更导致 DTO 映射错误。
  • 防止敏感信息泄露:如 password_hash、profile 等字段不会被意外返回。
  • JPA/Hibernate 更高效:避免加载不需要的字段,减少实体初始化开销。

📌 Java 开发提示:MyBatis 中使用 resultMap 或 Spring Data JPA 中使用 Projection 可精准控制字段。


2. 🔍 使用 LIMIT 和 OFFSET 时,警惕深度分页性能问题

-- ❌ 深度分页慢(跳过 10 万条)
SELECT id, title FROM articles ORDER BY created_at DESC LIMIT 10 OFFSET 100000;

-- ✅ 推荐:游标分页(Cursor-based Pagination)
SELECT id, title, created_at 
FROM articles 
WHERE created_at < '2024-01-01 00:00:00'  -- 上一页最后一条的 created_at
ORDER BY created_at DESC 
LIMIT 10;

原因:

  • OFFSET N 会扫描前 N 条数据,N 越大越慢,时间复杂度 O(N)。
  • 游标分页基于索引条件查询,性能稳定,接近 O(1)。
  • 特别适合内容流、日志、订单列表等大数据量场景。

📌 适用场景:信息流、后台管理列表、审计日志等。


3. 🧱 为查询字段创建合适的索引

-- 查询常用字段:username, email
CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);

-- 复合索引:状态 + 时间(如订单筛选)
CREATE INDEX idx_orders_status_created ON orders(status, created_at DESC);

-- JSONB 字段索引(如 profile->>'nick')
CREATE INDEX idx_users_profile_nick ON users USING GIN ((profile->>'nick'));

原因:

  • 没有索引的 WHERE、ORDER BY 会导致全表扫描(Seq Scan),性能极差。
  • 正确的索引可将查询从 秒级降到毫秒级。
  • PostgreSQL 支持多种索引类型(B-tree、GIN、BRIN),应根据数据类型选择。

📌 建议:使用 EXPLAIN ANALYZE 检查查询是否走索引。


4. 🧩 优先使用 JOIN 而不是在 Java 中拼接数据

-- ✅ 推荐:一次查询完成关联
SELECT u.username, o.order_no, o.amount 
FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.id = '123';

而不是:

// ❌ 不推荐:N+1 查询问题
User user = userRepository.findById("123");
List<Order> orders = orderRepository.findByUserId("123"); // 每次查一次数据库

原因:

  • 减少数据库连接次数,降低网络延迟。
  • 避免 N+1 查询问题,这是性能杀手。
  • 数据库擅长关联计算,Java 层做关联效率低。

📌 Spring Data JPA 提示:使用 @EntityGraph 或 JOIN FETCH 避免 N+1。


5. 🧠 复杂统计逻辑尽量在数据库层完成

-- ✅ 推荐:在数据库中完成分组统计
SELECT 
    status,
    COUNT(*) AS count,
    SUM(amount) AS total
FROM orders 
GROUP BY status;

而不是:

// ❌ 不推荐:拉全量数据到 Java 层处理
List<Order> orders = orderRepository.findAll();
Map<String, Long> countByStatus = orders.stream()
    .collect(groupingBy(Order::getStatus, counting()));

原因:

  • 数据库的 GROUP BY 使用索引和并行计算,远快于 Java Stream。
  • 减少网络传输数据量(只传聚合结果,不传原始数据)。
  • 降低应用服务器内存压力。

6. 🧩 使用 CTE(公共表表达式)提升复杂 SQL 可读性

WITH recent_orders AS (
    SELECT user_id, SUM(amount) AS total
    FROM orders 
    WHERE created_at > NOW() - INTERVAL '30 days'
    GROUP BY user_id
)
SELECT u.username, ro.total 
FROM users u
JOIN recent_orders ro ON u.id = ro.user_id
ORDER BY ro.total DESC;

原因:

  • 将复杂查询拆分为逻辑块,类似 Java 中的变量命名。
  • 提高 SQL 可读性和可维护性。
  • 避免嵌套子查询导致的“括号地狱”。

7. 📊 合理使用窗口函数替代 Java 循环逻辑

-- 计算每个用户的订单排名
SELECT 
    user_id,
    order_no,
    amount,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at) AS rn
FROM orders;

原因:

  • 窗口函数是数据库原生支持的高效计算。
  • 替代 Java 中的 for 循环 + Map<UserId, List<Order>> + 排序。
  • 性能更好,代码更简洁。

8. 🧲 使用 CASE WHEN 在 SQL 层做数据转换

SELECT 
    status,
    CASE 
        WHEN status = 'paid' THEN '已支付'
        WHEN status = 'shipped' THEN '已发货'
        ELSE '其他'
    END AS status_text
FROM orders;

原因:

  • 减少 Java 中的 if-else 或 switch 判断。
  • 接口返回字段直接可用,无需额外转换。
  • 适合状态、类型等枚举字段的展示层转换。

9. 🔐 避免在 WHERE 中使用函数包裹字段(破坏索引)

-- ❌ 破坏索引,无法使用 created_at 索引
SELECT * FROM users WHERE DATE(created_at) = '2024-01-01';

-- ✅ 推荐:使用范围查询
SELECT * FROM users 
WHERE created_at >= '2024-01-01' 
  AND created_at < '2024-01-02';

原因:

  • WHERE DATE(created_at) = ... 会导致全表扫描。
  • 正确写法可利用 B-tree 索引,性能提升百倍。

10. 🧪 开发阶段使用 EXPLAIN ANALYZE 分析慢查询

EXPLAIN ANALYZE 
SELECT * FROM orders WHERE user_id = '123' AND status = 'paid';

原因:

  • 查看是否走索引(Index Scan vs Seq Scan)
  • 发现性能瓶颈(如 Nested Loop、Hash Join 成本)
  • 优化 SQL 和索引设计

📌 建议:在 DataGrip 中开启“Auto Explain”功能,自动分析执行计划。


11. 🧩 使用 JSONB 字段存储灵活数据,但查询要合理

-- ✅ 合理查询 JSONB
SELECT * FROM users WHERE profile->>'age' = '28';

-- ⚠️ 避免频繁查询深层嵌套字段
-- 建议:将高频查询字段提升为独立列(如 age INT)

原因:

  • JSONB 适合存储配置、扩展字段。
  • 但频繁查询 JSONB 字段会影响性能,建议为常用字段建 GIN 索引或拆分为独立列。

12. 🧩 生产环境避免在 SELECT 中使用 NOW()、CURRENT_USER() 等动态函数

-- ❌ 不推荐:在查询中使用 NOW(),影响缓存和计划复用
SELECT * FROM orders WHERE created_at > NOW() - INTERVAL '1 hour';

-- ✅ 推荐:由应用传参
-- PreparedStatement: WHERE created_at > ?

原因:

  • 动态函数导致每次查询的执行计划不同,无法复用执行计划缓存。
  • 使用参数化查询更安全(防 SQL 注入)、更高效。

✅ 总结:PostgreSQL SELECT 查询推荐做法一览表

建议原因适用场景
✅ 明确字段,不用 *减少传输、避免敏感字段泄露所有查询
✅ 使用 LIMIT/OFFSET 或游标分页避免深度分页性能问题列表接口
✅ 为查询字段建索引避免全表扫描高频查询字段
✅ 用 JOIN 替代 N+1 查询减少数据库访问次数关联查询
✅ 统计在数据库层完成性能高、减少数据传输报表、分析
✅ 使用 CTE 提升可读性结构清晰,易于维护复杂查询
✅ 使用窗口函数替代 Java 循环排名、累计
✅ 用 CASE WHEN 做转换减少 Java 判断状态展示
✅ 避免 WHERE 中用函数保持索引可用时间、字符串处理
✅ 用 EXPLAIN ANALYZE 优化定位性能瓶颈慢查询排查
✅ JSONB 查询建索引提升半结构化查询性能扩展字段
✅ 参数化查询安全、可缓存所有动态条件

🎁 附加建议:Java 开发者如何落地这些实践?

  1. 与 DBA 或架构师协作:定期 review 慢查询日志。
  2. 使用 Spring Boot Actuator + Prometheus:监控 SQL 执行时间。
  3. 代码审查中加入 SQL 检查项:禁止 SELECT *、N+1 查询。
  4. 使用 QueryDSL 或 jOOQ:生成类型安全、可优化的 SQL。
  5. 定期执行 ANALYZE TABLE:更新统计信息,帮助优化器生成更好执行计划。
Python自动化神器:OP插件64位版从安装到实战(附雷电模拟器截图技巧) 本文详细介绍了Python自动化神器OP插件64位版的安装与实战应用,包括环境搭建、窗口控制、鼠标键盘模拟等核心功能。特别针对雷电模拟器提供了最小化截图技术和OCR识别优化方案,帮助开发者高效实现Windows自动化任务。 阅读详情

相关推荐

5QI(5G QoS Identifier)

此外,5QI与网络切片(Network Slicing)密切相关,网络切片允许网络运营商在物理网络内部创建虚拟网络,为不同的客户和用例提供定制化服务和QoS。5QI(5G QoS Identifier)在5G网络中用于标识不同的服务质量要求,它允许网络对不同的数据流进行优先级划分和资源分配。:5QI的实施需要对5G网络的QoS参数有深入的理解,包括延迟、吞吐量、数据包丢失率等,这对技术人员提出了较高的要求。不是所有的5G设备都支持5QI的全部功能,这可能会限制5QI应用的广泛性。

记录有价值的内容 6528

MySQL中Select语句返回用List来接收

MySQL根据条件查询Select记住,永远用List&lt;&gt;几首返回。对于,确定只有单条记录,一般我的写法为:public int getPayStatusByPayno(OrderInfoRequest orderInfoRequest) { if (orderInfoRequest == null) { throw new DonationException(...

timchen525的专栏 1万+

利用Openlayers4实现地图遮罩效果(二)

之前实现的遮罩效果,在深色背景的底图上,对要突出的区域采用半透明遮罩,以此来突出该区域。但是有时底图颜色偏白,这时候不再适合对要突出的区域采用遮罩,而是要对突出区域之外进行遮罩处理。两种效果的对比入下图: ...

此爱如少年 6395

SELECT * 语句的缺点

1、SELECT * 语句取出表中的所有字段,不论该字段的数据对调用的应用程序是否有用,这会对服务器资源造成浪费,甚至会对服务器的性能产生一定的影响。 2、如果表的结构在以后发生了改变,那么SELECT * 语句可能会取到不正确的数据甚至是出错。 3、执行SELECT * 语句时,SQL Server首先要查找出表中有哪些列,然后才能开始执行SELECT * 语句,这在某些情况会产生性

TongYu2009的专栏 6562

深入解析TOM模块的PWM输出与ADC触发机制:从配置到DMA数据传输

本文深入解析了TOM模块在嵌入式系统中的核心应用,详细阐述了如何配置其PWM输出功能,并实现与ADC模块的硬件触发同步。重点介绍了通过DMA机制高效传输ADC采样数据的完整流程,涵盖时钟配置、工作模式选择、引脚映射及联调实战,为电机控制、数字电源等实时系统提供了一套硬件自动化的高效解决方案。

weixin_29227585的博客 367

从零构建FOC:手把手教你实现无刷电机磁场定向控制

本文是一份详尽的FOC(磁场定向控制)实战教程,指导开发者从零开始构建无刷电机驱动系统。文章深入解析了FOC的核心算法,包括坐标变换(Clarke/Park)、SVPWM调制和双环PI控制,并对比了有感与无感方案的实现差异。通过分步调试指南,帮助读者亲手实现稳定、高效的无刷电机控制,彻底掌握其底层原理。

h3i4j的博客 514

mysql报错115_mysql报错Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated ...

今天sql一对多关联查询发现一个错误,提示说查询的字段不在group by的子句中,因为sql_mode是only_full_group_by。报错信息:#1055 - Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'xt_sc.t_comment.content' ...

weixin_32340873的博客 1046

手把手教你学Simulink--基于飞行控制与稳定性的场景实例:固定翼无人机的自动起飞与降落控制

本文介绍了使用Simulink对固定翼无人机自动起飞与降落控制系统进行建模与仿真的完整流程。首先构建了包含飞行器动力学模型、控制系统、环境模拟等模块的系统结构,详细阐述了简化动力学方程的推导和实现。重点讲解了PID控制器设计,包括起飞阶段的速度控制和降落阶段的高度控制策略。通过添加环境干扰和输入信号,建立了完整的仿真模型,并利用输出显示模块评估系统性能。该实例为无人机自主控制系统的开发提供了有效的仿真验证方法,有助于优化参数提高飞行稳定性。

MHD0815的博客 4308

MYSQL ——select查询

需要注意的是,尽管可以查询指定列的数据,但是这并不意味着仅查询这些列的效率一定比查询所有列的效率高。因此,在实际应用中,需要慎重考虑筛选条件和聚合函数的使用,以便获得更好的查询性能。因此,在编写 SQL 语句之前,需要对数据库结构有一定的了解,并根据具体需求来设计表结构、索引、视图等数据库对象。此外,在查询过程中还需要遵循数据库的约束条件,例如表关系、数据类型等,以保证查询结果的正确性。是非常方便的查询方式,但是并不推荐在实际应用中频繁使用,因为它可能会返回大量的数据,从而影响查询性能和网络带宽。

lsj614的博客 6132

视觉自动对焦(Z 轴运动 + 相机拍照 + 清晰度计算) 的核心程序

控制 Z 轴匀速扫动一段距离,在移动过程中等间距触发相机拍照,后台计算每张图的清晰度,最后移动到最清晰的位置,完成自动对焦。

StevenChen的博客 306

RK3588 部署 YOLO26 目标检测:从训练到 NPU 推理

如果做垂直场景(工业缺陷、农作物、特定零件),需要自己标数据。采集图像(500+ 张,覆盖不同光照/角度)→ 筛选(删除模糊/无目标)→ LabelImg 标注(选择 YOLO 格式)→ 划分(train:val:test = 7:2:1)labelImg├── train/├── val/├── test/YOLO26 在 RK3588 上的全流程是 PC 端训练 + ONNX 导出 → RKNN 转换(INT8 量化)→ 板端推理。

m0_71589036的博客 107

SELECT 查询的基础语法

查询列 SELECT name FROM heros; (单列) SELECT name, hp_max, mp_max FROM heros; (多列) SELECT * FROM heros; (所有列) 起别名 SELECT name AS n FROM heros; (AS 可以省略) 查询常数 字符串都用单引号 SELECT '王者荣耀' as platform, name FROM heros 去除重复行 SELECT DISTINCT attack_range FROM heros;

Megetood的博客 644

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

MySQL之SELECT查询语句

  查询数据是数据库操作中最重要的操作之一,实现查询操作要使用SQL语言中的SELECT语句。使用SELECT检索表数据,要明确两点,一是想选择什么,二是从什么地方选择。 SELECT语句的基本语法格式 下面先介绍SELECT语句最基本的语法格式。 SELECT * FROM table SELECT关键字后的“*”,代表查询数据表中的所有(字段)的内容,同时也可以指定要查询的字段名列表。 FROM关键字后的table,指明要从哪个表查询数据。 SELECT语句与其他SQL语句一样,不区分大小写,例如

weixin_47011419的博客 1444

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

【数据库】 为什么不推荐使用select * 进行查询?

为什么不推荐使用select * 查询 ??之前没有了解过这个问题,结果就在面试中遇到了,没有回答好,所以还是多多总结!

Moo_Lavender的博客 1664

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

为什么不推荐使用 select * ?是性能问题吗 ?

作者 孤独烟,中国平安研发工程师,目前负责云平台架构设计以及需求研发工作。毕业后一直从事Java开发工作,在Web开发、架构设计上有多年的实战经验。在MySQL性能优化、JVM调优、分布式领域有着丰富的经验。 引言 大家在开发中,还有很多童鞋在写查询语句的时候,习惯写下面这种不规范sql select * from table 而不写成下面的这种规范方式 select col1,...

KHOST的博客 1万+

mysql select 运算_MYSQL中的SELECT查询时进行运算

SELECT在mysql中是查询表中的数据的作用,但也可以在查询的时候直接进行运算,然后返回查询后的结果比如SELECT user,math*(IFNULL(adven,0)) FROM username2其中的IFNULL函数是对adven数据进行判断,若adven中的数据不为NULL,则返回adven本身的数据,若为NULL,则返回0。其它+,-,/的运算也可以如同上面的代码进行替换而已。更多...

weixin_32676541的博客 3607

Oracle语句第10期:SELECT 查询的高频用法核心要点

本文详解Oracle SELECT语句的高频用法:1)基础查询包括列选择、别名、去重和WHERE条件过滤;2)聚合查询使用GROUP BY分组和HAVING过滤;3)多表关联推荐ANSI标准JOIN语法;4)分页查询通过ROWNUM实现;5)子查询分为单行、多行和关联子查询;6)常用字符串和日期函数。掌握这些核心用法可满足90%以上的业务查询需求,重点注意生产环境避免SELECT*、正确使用NULL判断和JOIN关联方式选择。

CC的博客 1298

Memento查询系统深度解析:match、select、select_raw三种查询方式对比

Memento作为Mnesia分布式数据库的简洁而强大的接口,提供了三种高效的查询方式:match、select和select_raw。这些查询方法各具特色,适用于不同的使用场景,帮助开发者轻松操作分布式数据库。本文将深入对比这三种查询方式的特点、使用方法和适用场景,助你快速掌握Memento查询系统的精髓。 [![Memento数据库查询系统](https://raw.gitcode.com/

gitblog_00437的博客 901

PostgreSQL 常用 SELECT 数据查询命令

PostgreSQL SELECT 命令实用指南 SELECT 是 PostgreSQL 中最核心的查询命令,掌握其用法能显著提升开发效率。本文从基础到高级,通过 12 个实用示例讲解 SELECT 的用法: 基础查询:SELECT * FROM users 指定字段:SELECT username, email FROM users 条件查询:WHERE username = 'zhangsan' 模糊查询:ILIKE 和 JSONB 搜索 分页查询:LIMIT 10 OFFSET 10 去重查询:DIS

python15397的博客 1072

select * 和 select 所有字段的区别

程序员的成长之路互联网/程序员/成长/职场关注阅读本文大概需要 1 分钟。之前发过的文章中,关于 select * 和 select 所有字段的知识,有描述不恰当,这次...

良月柒 3万+

select *与select 所有字段的查询效率比较

ysql 5.1.37 表记录数41,547,002,即4000w行 使用远程客户端取1000条数据,统计时间: SELECT * FROM dmsp.dmsp_dimension_content LIMIT 0, 1000; 时间2.218s,网络消耗0.547s SELECT id, appid, aop, t, uid, sid, pid, pname, bid, bname, ptyp

figerZpeng的专栏 2万+

MySQL 将查询结果导出到文件(select … into Statement)

select…select … into @var_list from …. 将查询结果写入到一组变量select … into outfile from …. 将数据写入操作系统文件,可以自定义数据格式(分隔符、包裹符、转义符、换行符等)。select … into dumpfile from …. 将单一行写入文件,没有任何格式化。

m0_74822999的博客 3486

SQL 查询语句先执行 SELECT?兄弟你认真的么?

理解。

每日一贴 1026

ClickHouse SELECT查询深度解析

ClickHouse SELECT查询深度解析 【免费下载链接】ClickHouse ClickHouse® 是一个免费的大数据分析型数据库管理系统。 项目地址: https://gitcode.com/GitHub_Trendi...

gitblog_00343的博客 502

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

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

weixin_34221374的博客 1757
上一篇: 10、添加布隆过滤器 + 延迟双删
下一篇: SELECT 的查询优化方案有哪些?
龙茶清欢
博客等级 码龄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、付费专栏及课程。

余额充值