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

sql 优化,提高查询速度

文章目录

  • 一、前言
  • 二、建议
    • 2.1 使用索引
    • 2.2 避免使用select *
    • 2.3. 使用表连接代替子查询
    • 2.4. 优化WHERE子句,减少返回结果集的大小
    • 2.5 用union all代替union
    • 2.6 使用合适的聚合策略
    • 2.7 避免在WHERE子句中使用函数
    • 2.8 使用EXPLAIN分析查询
    • 2.9 小表驱动大表
    • 2.10 使用窗口函数代替子查询
    • 2.11 使用适当的数据类型
    • 2.12 优化分页查询
    • 2.13 in中值太多
  • 三、总结


一、前言

在系统开发中,SQL查询的优化是提高应用性能和响应速度的关键。以下是SQL语句优化的建议,希望对您有帮助:

二、建议

2.1 使用索引

原因:索引可以极大地减少数据库需要扫描的数据量,加快查询速度。
建议:为查询中经常作为WHERE条件、JOIN条件或ORDER BY的列创建索引。

SQL例子:
假设有一个user表,经常按department_id查询

CREATE INDEX idx_department_id ON user(department_id);
SELECT * FROM user WHERE department_id = 20;

2.2 避免使用select *

原因:在实际业务场景中,可能我们真正需要使用的只有其中一两列。查了很多数据,但是不用,白白浪费了数据库资源,比如:内存或者cpu。
此外,多查出来的数据,通过网络IO传输的过程中,也会增加数据传输的时间。
还有一个最重要的问题是:select *不会走覆盖索引,会出现大量的回表操作,而从导致查询sql的性能很低。
建议:避免使用SELECT *,只选择需要的列。

SQL例子:
– 只需获取用户的姓名和部门ID

SELECT name, department_id FROM user;

2.3. 使用表连接代替子查询

原因:在某些情况下,JOIN操作比子查询更高效,因为JOIN允许数据库优化器更有效地执行查询计划。
建议:当可能时,使用JOIN代替子查询。

SQL例子:
使用JOIN

SELECT e.name, d.department_name
FROM user e
JOIN departments d ON e.department_id = d.id;

替代的子查询版本

SELECT e.name, (SELECT d.department_name FROM departments d WHERE d.id = e.department_id) AS department_name
FROM user e;

2.4. 优化WHERE子句,减少返回结果集的大小

原理:减少返回结果集的大小可以加快查询速度。
建议:在WHERE子句中过滤掉尽可能多的行。
SQL例子:
假设有大量的数据,但只对特定条件的记录感兴趣

SELECT * FROM orders WHERE status = 'inventory' AND order_date > '2024-01-01';

2.5 用union all代替union

原因:我们都知道sql语句使用union关键字后,可以获取排重后的数据。
而如果使用union all关键字,可以获取所有数据,包含重复的数据。
反例:

(select * from user where id=1) 
union 
(select * from user where id=2);

排重的过程需要遍历、排序和比较,它更耗时,更消耗cpu资源。
建议:如果能用union all的时候,尽量不用union。
正例:

(select * from user where id=1) 
union all
(select * from user where id=2);

除非是有些特殊的场景,比如union all之后,结果集中出现了重复数据,而业务场景中是不允许产生重复数据的,这时可以使用union。

2.6 使用合适的聚合策略

原因:合理使用GROUP BY和HAVING可以减少数据处理的复杂性。
建议:仅在必要时使用GROUP BY,并考虑使用HAVING代替WHERE对聚合结果进行过滤。

SQL例子:
对订单按状态分组,并筛选总金额超过一定值的组

SELECT status, COUNT(*), SUM(amount)
FROM orders
GROUP BY status
HAVING SUM(amount) > 1000;

2.7 避免在WHERE子句中使用函数

原因:在WHERE子句中对列使用函数会阻止索引的使用。
建议:尽可能避免在WHERE子句中对列使用函数。
SQL例子:
不推荐(可能无法利用索引)

SELECT * FROM user WHERE YEAR(hire_date) = 2020;

推荐

SELECT * FROM user WHERE hire_date >= '2020-01-01' AND hire_date < '2024-01-01';

2.8 使用EXPLAIN分析查询

原因:了解查询的执行计划和性能瓶颈。
建议:使用EXPLAIN或类似工具分析查询,并根据结果调整索引或查询结构。
SQL例子:
大多数数据库管理系统都支持EXPLAIN命令

EXPLAIN SELECT * FROM user WHERE department_id = 20;

2.9 小表驱动大表

小表驱动大表,也就是说用小表的数据集驱动大表的数据集。
假如有order和user两张表,其中order表有10000条数据,而user表有100条数据。
这时如果想查一下,所有有效的用户下过的订单列表。
可以使用in关键字实现:

select * from order
where user_id in (select id from user where status=1)

也可以使用exists关键字实现:

select * from order
where exists (select 1 from user where order.user_id = user.id and status=1)

前面提到的这种业务场景,使用in关键字去实现业务需求,更加合适。
为什么呢?
因为如果sql语句中包含了in关键字,则它会优先执行in里面的子查询语句,然后再执行in外面的语句。如果in里面的数据量很少,作为条件查询速度更快。
而如果sql语句中包含了exists关键字,它优先执行exists左边的语句(即主查询语句)。然后把它作为条件,去跟右边的语句匹配。如果匹配上,则可以查询出数据。如果匹配不上,数据就被过滤掉了。
这个需求中,order表有10000条数据,而user表有100条数据。order表是大表,user表是小表。如果order表在左边,则用in关键字性能更好。
总结一下:
in 适用于左边大表,右边小表。
exists 适用于左边小表,右边大表。
不管是用in,还是exists关键字,其核心思想都是用小表驱动大表。

2.10 使用窗口函数代替子查询

原因:窗口函数(如ROW_NUMBER()、RANK()等)可以在不改变结果集行数的情况下为每行提供额外的计算列,这通常比使用子查询更高效。
建议:当需要为结果集中的每行添加基于整个结果集的额外信息时,考虑使用窗口函数。
例子:
优化前(使用子查询计算排名)

SELECT id, name,(SELECT COUNT(*) + 1FROM users u2WHERE u2.score > u.score) AS rank
FROM users u;

优化后(使用窗口函数计算排名)

SELECT id, name,ROW_NUMBER() OVER (ORDER BY score DESC) AS rank
FROM users;

2.11 使用适当的数据类型

原因:选择合适的数据类型可以减少存储空间和查询时间。
建议:避免使用过大的数据类型,如使用INT代替VARCHAR存储数字。
SQL例子:
创建表时选择合适的数据类型

CREATE TABLE sales (id INT AUTO_INCREMENT,amount DECIMAL(10, 2),PRIMARY KEY (id)
);

2.12 优化分页查询

原因:当使用LIMIT和OFFSET进行分页时,随着页码的增加,查询性能会逐渐下降,因为数据库需要扫描越来越多的行来找到所需的起始点。
建议:使用基于索引的查询来优化分页,特别是当表很大时。例如,可以记录上一页最后一条记录的某个唯一标识符(如ID),并使用它作为下一页查询的起点。
例子:
优化前(随着页码增加性能下降)

SELECT * FROM user LIMIT 10 OFFSET 100;

优化后(使用上一页的最后一条记录的ID)

SELECT * FROM user WHERE id > LAST_SEEN_ID ORDER BY id LIMIT 10;

2.13 in中值太多

对于批量查询接口,我们通常会使用in关键字过滤出数据。比如:想通过指定的一些id,批量查询出用户信息。
sql语句如下:

select id,name from category
where id in (1,2,3...100000000);

如果我们不做任何限制,该查询语句一次性可能会查询出非常多的数据,很容易导致接口超时。
这时该怎么办呢?

select id,name from category
where id in (1,2,3...100)
limit 500;

可以在sql中对数据用limit做限制。
不过我们更多的是要在业务代码中加限制,伪代码如下:

public List<Category> getCategory(List<Long> ids) {if(CollectionUtils.isEmpty(ids)) {return null;}if(ids.size() > 500) {throw new BusinessException("一次最多允许查询500条记录")}return mapper.getCategoryList(ids);
}

还有一个方案就是:如果ids超过500条记录,可以分批用多线程去查询数据。每批只查500条记录,最后把查询到的数据汇总到一起返回。

不过这只是一个临时方案,不适合于ids实在太多的场景。因为ids太多,即使能快速查出数据,但如果返回的数据量太大了,网络传输也是非常消耗性能的,接口性能始终好不到哪里去。

三、总结

SQL查询的优化都是相对的,要根据具体业务和库表数据量的大小选择合适的优化方案。

相关文章:

sql 优化,提高查询速度

文章目录 一、前言二、建议2.1 使用索引2.2 避免使用select *2.3. 使用表连接代替子查询2.4. 优化WHERE子句&#xff0c;减少返回结果集的大小2.5 用union all代替union2.6 使用合适的聚合策略2.7 避免在WHERE子句中使用函数2.8 使用EXPLAIN分析查询2.9 小表驱动大表2.10 使用窗…...

springboot后端开发-自定义参数校验器

背景 在使用springboot进行后端开发的时候&#xff0c;经常会遇到数据校验的问题&#xff0c; 有时候可能默认的校验器不足以满足自己的需求&#xff0c; 这个时候就需要开发一个自己的校验器 在 Spring Boot 中自定义参数校验器通常涉及以下几个步骤&#xff1a; 1. 定义注解…...

springboot社区帮扶对象管理系统论文源码调试讲解

第2章 开发环境与技术 社区帮扶对象管理系统的编码实现需要搭建一定的环境和使用相应的技术&#xff0c;接下来的内容就是对社区帮扶对象管理系统用到的技术和工具进行介绍。 2.1 MYSQL数据库 本课题所开发的应用程序在数据操作方面是不可预知的&#xff0c;是经常变动的&…...

EmguCV学习笔记 VB.Net 6.2 轮廓处理

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…...

【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码

文章目录 一、游戏运行效果二、代码实现2.1 项目搭建2.2 加载我方坦克2.3 加载敌方坦克2.4 添加爆炸效果2.5 坦克大战之音效处理 三、完整代码 一、游戏运行效果 二、代码实现 坦克大战游戏 2.1 项目搭建 本游戏主要分为两个对象&#xff0c;分别是我方坦克和敌方坦克。用户可…...

【机器学习】经典CNN架构

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 经典CNN架构1. 引言2. LeNet3. AlexNet4. VGGNet5. GoogLeNet(Inception)6. Res…...

图像数据处理21

五、边缘检测 5.2基于二阶导数的边缘检测 一阶导数&#xff08;如Sobel、Prewitt算子&#xff09;能够捕捉到灰度值的快速变化&#xff0c;但有时会因检测到过多的边缘点而导致边缘线过粗。为了更加精确地定位边缘位置&#xff0c;可以利用二阶导数的零交叉点。零交叉点是是函…...

day37动态规划+三.Github链接本地仓库

一.动态规划 474.一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度&#xff0c;该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素&#xff0c;集合 x 是集合 y 的 子集 。 思路:这道题更像是另一种的0-…...

设备运维故障排查与修复技巧

运维中最常见的40个故障问题及其解决方法: 1. 网络不通问题:无法访问网络资源。 解决方法:检查物理线路、交换机端口、网卡驱动和配置,使用ping、traceroute等工具定位问题。 2. 网络速度慢问题:访问网络资源速度慢。 解决方法:分析带宽使用情况,检查是否存在广播风…...

探索Python的自动化魔法:AutoIt库揭秘

文章目录 探索Python的自动化魔法&#xff1a;AutoIt库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;AutoIt是什么&#xff1f;第三部分&#xff1a;如何安装AutoIt库&#xff1f;第四部分&#xff1a;AutoIt的五个简单函数第五部分&#xff1a;场景应用第六部分&…...

【I/O多路复用】

基于I/O多路复用的并发编程 I/O实现I/O多路复用select优缺点 pollepoll优点 I/O I/O复用是基于一个单进程或单线程的一个执行流当中监控多个输入输出流的技术&#xff08;网络套接字或者文件描述符进行监控&#xff09;。单进程或单线程&#xff0c;允许多个用户对单进程发起连…...

【python报错已解决】“IndexError: list index out of range”

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 你是否在处理Python列表时遇到了“IndexError: list index out of range”的错误&#xff1f;这个错误可能会让你的程序中…...

oracle和mysql查询某字段在哪个表中

oracle和mysql查询某字段在哪个表中 oracle的 select TABLE_NAME from user_tab_columns where COLUMN_NAME字段名mysql的&#xff1a; select table_schema ,table_name from information_schema.columns where column_name ‘字段名’ 查询结果table_schema为数据库名&a…...

TCP vs UDP:揭秘可靠性与效率之争

概述 今天我们开始主要讲解TCP的相关知识点。在之前讲解分层章节的时候&#xff0c;我们提到过一个重要观点。在网络层及以下几层&#xff0c;更多的是让主机与主机建立连接&#xff0c;也就是说你的电脑需要知道另一台电脑在哪里才能连接上它。然而&#xff0c;在网络中的通信…...

“树”的高度的计算——CSP-J1真题详解

如同树有高度一样&#xff0c;数据结构中的“树”也有高度&#xff0c;只不过这个高度指的是第几“层”。就像武功可以修炼到第几层一样&#xff0c;树也可以长到第几层。 需要指明的是&#xff0c;树的根节点属于第几层是没有严格的定义的&#xff0c;一般被认为是处于第0层或…...

Docker介绍、docker安装以及实现docker的远程管理

1.Docker介绍 1.Docker介绍 Docker 是⼀个开源的应用容器引擎&#xff0c;可以实现虚拟化&#xff0c;完全采用“沙盒”机制&#xff0c;容器之间不会存在任何接口。 Docker 通过 Linux Container&#xff08;容器&#xff09;技术将任意类型的应用进行包装&#xff0c;变成一…...

【UE5】基于摄像机距离逐渐剔除角色

效果 步骤 1. 新建一个工程&#xff0c;在内容浏览器中添加第三人称游戏内容包 2. 找到第三人称角色的材质实例“MI_Quinn_01”并打开 找到材质实例的父项材质“M_Mannequin” 打开材质“M_Mannequin” 在材质图表中添加如下节点 此时运行效果如文章开头所示。 参考视频&#…...

LabVIEW优化内存使用

在LabVIEW中&#xff0c;优化内存使用的关键在于理解LabVIEW的内存管理机制并采用一些最佳实践。以下是一些可能帮助减少内存占用的方法&#xff1a; 1. 减少数据副本的生成 避免不必要的数据复制&#xff1a;每当你在程序中传递数组或子数组时&#xff0c;LabVIEW可能会创建副…...

多进程和多线程基础概念LINUX

进程和程序的区别 程序是静态的&#xff0c;它是保存在磁盘上的指令的有序集合&#xff0c;没有任何执行的概念进程是一个动态的概念&#xff0c;它是程序执行的过程&#xff0c;包括了动态创建、调度和销毁的整个过程 并行&#xff1a;在 cpu 多核的支持下&#xff0c;实现物…...

React Native的Android端fetch的网络请求FormData请求错误:TypeError:Network request failed

// formdataconst formData new FormData();formData.append("code", appUserCode);formData.append("wallet", appName);// const formDataStr code appUserCode &wallet appName;// 参数形式//const _body code${appUserCode}&wallet${app…...

Windows系统优化新选择:WinUtil一键式管理工具实用指南

Windows系统优化新选择&#xff1a;WinUtil一键式管理工具实用指南 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil 你是否曾为Windows系统的繁…...

500+ RPG Maker插件终极指南:如何快速提升游戏开发效率

500 RPG Maker插件终极指南&#xff1a;如何快速提升游戏开发效率 【免费下载链接】RPGMakerMV RPGツクールMV、MZで動作するプラグインです。 项目地址: https://gitcode.com/gh_mirrors/rp/RPGMakerMV RPG Maker开发者们&#xff0c;你们是否曾为游戏开发中的各种限制…...

Upscayl GPU加速问题终极解决方案:快速修复Vulkan兼容性错误

Upscayl GPU加速问题终极解决方案&#xff1a;快速修复Vulkan兼容性错误 【免费下载链接】upscayl &#x1f199; Upscayl - #1 Free and Open Source AI Image Upscaler for Linux, MacOS and Windows. 项目地址: https://gitcode.com/GitHub_Trending/up/upscayl Upsc…...

尝试以底层角度,理解c++代码书写逻辑

大家好&#xff0c;现在是4月10号下午6点7分&#xff0c;又来写blog了&#xff01;废话不多说&#xff0c;我来写写要将内容的大纲&#xff1a;一&#xff1a;由c转为c时&#xff0c;写代码时出现的困惑二&#xff1a;实验性理论开发之路三&#xff1a;理论哈哈&#xff0c;就三…...

终极指南:Adafruit GFX库带你轻松玩转嵌入式图形编程

终极指南&#xff1a;Adafruit GFX库带你轻松玩转嵌入式图形编程 【免费下载链接】Adafruit-GFX-Library Adafruit GFX graphics core Arduino library, this is the core class that all our other graphics libraries derive from 项目地址: https://gitcode.com/gh_mirror…...

bitcoin-arbitrage自动化交易实战:TraderBot和TraderBotSim详解

bitcoin-arbitrage自动化交易实战&#xff1a;TraderBot和TraderBotSim详解 【免费下载链接】bitcoin-arbitrage Bitcoin arbitrage - opportunity detector 项目地址: https://gitcode.com/gh_mirrors/bi/bitcoin-arbitrage 在加密货币交易领域&#xff0c;利用不同交易…...

终极显卡驱动清理指南:DDU工具完整使用教程

终极显卡驱动清理指南&#xff1a;DDU工具完整使用教程 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-uninstaller Displ…...

初中物理资源合集

初中物理网课全套 文件大小: 18.9GB内容特色: 覆盖初中物理全部知识点适用人群: 初一至初三学生、家长及教师核心价值: 名师讲解体系化课程&#xff0c;轻松提分下载链接: https://pan.quark.cn/s/6a6b2ff65dbb 初中物理教案课件 文件大小: 3.3GB内容特色: 3.3GB初中物理全套…...

如何用3分钟将B站视频转成文字稿?这个免费开源工具让你告别手动记录

如何用3分钟将B站视频转成文字稿&#xff1f;这个免费开源工具让你告别手动记录 【免费下载链接】bili2text Bilibili视频转文字&#xff0c;一步到位&#xff0c;输入链接即可使用 项目地址: https://gitcode.com/gh_mirrors/bi/bili2text 你是否曾经面对长达几小时的B…...

Cursor报错user is unauthorized?3种快速解决方法(附官方推荐安装指南)

Cursor报错"user is unauthorized"的深度排查与解决方案 1. 理解"user is unauthorized"错误的本质 当你满怀期待地打开Cursor准备开始一天的编码工作&#xff0c;却突然看到"user is unauthorized"的红色错误提示时&#xff0c;那种感觉就像被…...