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子句,减少返回结果集的大小2.5 用union all代替union2.6 使用合适的聚合策略2.7 避免在WHERE子句中使用函数2.8 使用EXPLAIN分析查询2.9 小表驱动大表2.10 使用窗…...
springboot后端开发-自定义参数校验器
背景 在使用springboot进行后端开发的时候,经常会遇到数据校验的问题, 有时候可能默认的校验器不足以满足自己的需求, 这个时候就需要开发一个自己的校验器 在 Spring Boot 中自定义参数校验器通常涉及以下几个步骤: 1. 定义注解…...

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

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

【Python的魅力】:利用Pygame实现游戏坦克大战——含完整源码
文章目录 一、游戏运行效果二、代码实现2.1 项目搭建2.2 加载我方坦克2.3 加载敌方坦克2.4 添加爆炸效果2.5 坦克大战之音效处理 三、完整代码 一、游戏运行效果 二、代码实现 坦克大战游戏 2.1 项目搭建 本游戏主要分为两个对象,分别是我方坦克和敌方坦克。用户可…...

【机器学习】经典CNN架构
🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 💫个人格言: "如无必要,勿增实体" 文章目录 经典CNN架构1. 引言2. LeNet3. AlexNet4. VGGNet5. GoogLeNet(Inception)6. Res…...

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

day37动态规划+三.Github链接本地仓库
一.动态规划 474.一和零 给你一个二进制字符串数组 strs 和两个整数 m 和 n 。 请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。 如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。 思路:这道题更像是另一种的0-…...
设备运维故障排查与修复技巧
运维中最常见的40个故障问题及其解决方法: 1. 网络不通问题:无法访问网络资源。 解决方法:检查物理线路、交换机端口、网卡驱动和配置,使用ping、traceroute等工具定位问题。 2. 网络速度慢问题:访问网络资源速度慢。 解决方法:分析带宽使用情况,检查是否存在广播风…...

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

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

【python报错已解决】“IndexError: list index out of range”
🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 你是否在处理Python列表时遇到了“IndexError: list index out of range”的错误?这个错误可能会让你的程序中…...
oracle和mysql查询某字段在哪个表中
oracle和mysql查询某字段在哪个表中 oracle的 select TABLE_NAME from user_tab_columns where COLUMN_NAME字段名mysql的: select table_schema ,table_name from information_schema.columns where column_name ‘字段名’ 查询结果table_schema为数据库名&a…...

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

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

Docker介绍、docker安装以及实现docker的远程管理
1.Docker介绍 1.Docker介绍 Docker 是⼀个开源的应用容器引擎,可以实现虚拟化,完全采用“沙盒”机制,容器之间不会存在任何接口。 Docker 通过 Linux Container(容器)技术将任意类型的应用进行包装,变成一…...

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

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

多进程和多线程基础概念LINUX
进程和程序的区别 程序是静态的,它是保存在磁盘上的指令的有序集合,没有任何执行的概念进程是一个动态的概念,它是程序执行的过程,包括了动态创建、调度和销毁的整个过程 并行:在 cpu 多核的支持下,实现物…...
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…...

XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...

业务系统对接大模型的基础方案:架构设计与关键步骤
业务系统对接大模型:架构设计与关键步骤 在当今数字化转型的浪潮中,大语言模型(LLM)已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中,不仅可以优化用户体验,还能为业务决策提供…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...