经验笔记:SQL调优
SQL调优经验笔记
引言
SQL调优是确保数据库系统高效运行的重要环节。通过对查询语句、数据库配置、硬件资源等方面进行优化,可以显著提升数据库性能,进而增强应用程序的整体表现。以下是基于常见调优手段和实践经验整理的一份经验笔记。
1. 查询语句优化
- 1.1 避免使用
SELECT *
只选择需要的列,减少不必要的数据传输。
示例:
-- 不推荐
SELECT * FROM users WHERE id = 1;-- 推荐
SELECT first_name, last_name, email FROM users WHERE id = 1;
- 1.2 用
UNION ALL
代替UNION
UNION ALL
不进行去重操作,执行速度更快。
示例:
-- 不推荐
(SELECT first_name, last_name FROM users WHERE city = 'New York')
UNION
(SELECT first_name, last_name FROM users WHERE city = 'Los Angeles');-- 推荐
(SELECT first_name, last_name FROM users WHERE city = 'New York')
UNION ALL
(SELECT first_name, last_name FROM users WHERE city = 'Los Angeles');
-
1.3 小表驱动大表
描述:在连接查询中,如果有一个小表和一个大表,应该优先使用小表来驱动大表,以减少处理的数据量。
不推荐:
SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE u.status = 'active';
这个查询会先从
orders
表开始,然后对于每一个orders
表中的记录,都会去users
表中查找匹配的记录。如果orders
表很大,而符合条件的users
很少,那么这种查询效率不高。推荐:
SELECT * FROM orders o WHERE o.user_id IN (SELECT id FROM users WHERE status = 'active');
这个查询先从
users
表中找出所有状态为active
的用户ID,然后从orders
表中选择那些用户ID包含在这些活跃用户ID中的订单记录。这种方式减少了处理orders
表的数据量。 -
1.4 批量操作
批量插入或更新数据,减少请求次数,提高性能。
示例:-- 不推荐 INSERT INTO orders (order_id, product_id, quantity) VALUES (1, 1, 10); INSERT INTO orders (order_id, product_id, quantity) VALUES (2, 2, 20); INSERT INTO orders (order_id, product_id, quantity) VALUES (3, 3, 30);-- 推荐 INSERT INTO orders (order_id, product_id, quantity) VALUES (1, 1, 10), (2, 2, 20), (3, 3, 30);
-
1.5 多用
LIMIT
限制查询结果的数量,提高查询效率。
示例:-- 不推荐 SELECT * FROM orders ORDER BY order_date DESC;-- 推荐 SELECT * FROM orders ORDER BY order_date DESC LIMIT 10;
-
1.6 限制
IN
子句中的值
避免查询大量数据导致接口超时。
示例:-- 不推荐 SELECT * FROM categories WHERE id IN (1, 2, 3, ..., 10000);-- 推荐 SELECT * FROM categories WHERE id IN (1, 2, 3, ..., 100) LIMIT 500;
-
1.7 增量查询
通过条件限制,每次只查询部分数据,提高同步效率。
示例:-- 不推荐 SELECT * FROM users WHERE create_time > '2024-01-01';-- 推荐 SELECT * FROM users WHERE id > #{lastId} AND create_time >= #{lastCreateTime} LIMIT 100;
-
1.8 高效的分页
使用ID范围查询代替偏移量分页。
示例:-- 不推荐 SELECT * FROM users LIMIT 1000, 20;-- 推荐 SELECT * FROM users WHERE id > 1000000 LIMIT 20;
-
1.9 用连接查询代替子查询
描述:使用连接查询而不是子查询,以减少临时表的创建,提高查询效率。
不推荐:
SELECT * FROM orders WHERE user_id = (SELECT id FROM users WHERE status = 'active');
这里假设只有一个用户的
status
为active
。如果有多条记录符合条件,那么子查询将返回多行结果,可能导致内部错误或低效的处理。推荐:
SELECT o.* FROM orders o INNER JOIN users u ON o.user_id = u.id WHERE u.status = 'active';
这个查询通过连接两个表直接获取结果,减少了因子查询导致的临时表创建。
-
1.10 JOIN的表不宜过多
控制JOIN表的数量,避免复杂的索引选择。
示例:-- 不推荐 SELECT a.name, b.name, c.name FROM a INNER JOIN b ON a.id = b.a_id INNER JOIN c ON c.b_id = b.id;-- 推荐 SELECT a.name, b.name FROM a INNER JOIN b ON a.id = b.a_id;
-
1.11 JOIN时注意小表驱动大表
描述:使用INNER JOIN时,应让小表驱动大表;使用LEFT JOIN时,左边应为小表。
不推荐:
SELECT o.id, o.code, u.name FROM orders o LEFT JOIN users u ON o.user_id = u.id WHERE u.status = 'active';
这个查询使用了LEFT JOIN,意味着
orders
表中的每一行都会被处理,即使users
表中没有匹配的记录。如果orders
表很大,而users
表中符合条件的记录很少,这会导致很多空值的行。推荐:
SELECT o.id, o.code, u.name FROM orders o INNER JOIN users u ON o.user_id = u.id WHERE u.status = 'active';
这个查询只返回
orders
表中那些其user_id
在符合条件的users
表中的记录,这样可以减少处理的数据量。 -
1.12 控制索引的数量
合理控制索引数量,避免过多的索引导致性能消耗。
示例:-- 不推荐 CREATE INDEX idx_user_id ON orders (user_id); CREATE INDEX idx_order_date ON orders (order_date); CREATE INDEX idx_product_id ON orders (product_id);-- 推荐 CREATE INDEX idx_user_id_order_date ON orders (user_id, order_date);
-
1.13 选择合理的字段类型
根据数据特点选择合适的字段类型。
示例:-- 不推荐 ALTER TABLE orders ADD COLUMN order_code VARCHAR(20) NOT NULL;-- 推荐 ALTER TABLE orders ADD COLUMN order_code CHAR(10) NOT NULL;
-
1.14 提升
GROUP BY
的效率
在GROUP BY
前使用WHERE
条件过滤数据。
示例:-- 不推荐 SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;-- 推荐 SELECT user_id, COUNT(*) FROM orders WHERE user_id <= 200 GROUP BY user_id;
-
1.15索引优化
描述:使用
EXPLAIN
命令来检查SQL查询是否有效地利用了索引。不推荐:
SELECT * FROM orders WHERE code = '002';
如果
code
列上没有索引,那么数据库将执行全表扫描,这是低效的。推荐:
EXPLAIN SELECT * FROM orders WHERE code = '002';
通过
EXPLAIN
命令,我们可以看到查询计划,并确认是否使用了索引。如果未使用索引,可能需要考虑添加适当的索引。
2. 数据库配置
-
2.1 调整缓存大小
根据系统可用内存调整数据库缓存大小,以提高数据访问速度。
示例:-- MySQL示例 SET GLOBAL innodb_buffer_pool_size = 1G;
-
2.2 内存管理
优化内存分配,确保足够的内存用于缓存经常访问的数据。
示例:-- PostgreSQL示例 ALTER SYSTEM SET shared_buffers = '128MB';
-
2.3 事务隔离级别
根据应用程序的需求调整事务隔离级别,以平衡并发性和一致性。
示例:-- MySQL示例 SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
-
2.4 日志和备份设置
优化日志记录和备份策略,以减少对性能的影响。
示例:-- MySQL示例 SET GLOBAL log_bin_trust_function_creators = 1;
3. 硬件和基础设施
-
3.1 扩展硬件资源
增加更多的CPU核心、内存或更快的磁盘(如SSD)以提升性能。
示例:- 升级服务器硬件
- 使用固态硬盘(SSD)
-
3.2 分布式架构
采用分片(Sharding)、复制(Replication)等技术分散负载。
示例:- 使用分片技术将数据分布在不同的物理服务器上
- 设置主从复制,提高读写分离的能力
-
3.3 负载均衡
使用负载均衡器来分发请求,减轻单个服务器的压力。
示例:- 配置Nginx或HAProxy作为负载均衡器
4. 应用程序层面
-
4.1 缓存机制
在应用程序层面上实现缓存机制,减少对数据库的直接访问。
示例:- 使用Redis或Memcached作为缓存层
-
4.2 异步处理
对于耗时的操作,可以采用异步处理的方式,如队列或消息传递系统。
示例:- 使用RabbitMQ或Kafka作为消息队列
-
4.3 数据模型优化
重新设计数据模型,减少冗余,提高数据的一致性和可维护性。
示例:- 规范化数据表结构
- 减少冗余字段
5. 持续监测
-
5.1 性能监控
使用性能监控工具持续监控数据库的运行状况,及时发现性能下降的情况。
示例:- 使用Prometheus和Grafana进行性能监控
-
5.2 日志分析
定期分析数据库日志,查找可能导致性能问题的模式。
示例:- 使用Logstash收集日志
- 使用Elasticsearch进行日志分析
-
5.3 定期审查
定期审查SQL查询和数据库设计,寻找潜在的优化机会。
示例:- 定期进行代码审查
- 使用性能分析工具检查查询效率
6. 教育和培训
-
6.1 团队技能提升
确保开发团队有足够的知识来编写高效的SQL查询,并了解数据库的最佳实践。
示例:- 组织内部培训课程
- 分享最新的SQL调优技巧
-
6.2 持续学习
鼓励团队成员跟踪最新的数据库技术和优化策略。
示例:- 参加技术会议
- 阅读技术博客和论文
7. 实施步骤
-
7.1 制定计划
根据监测到的问题制定具体的优化计划。
示例:- 列出需要优化的SQL查询
- 确定需要调整的数据库配置
-
7.2 小规模测试
在不影响生产环境的情况下,先在一个小规模的环境中测试优化措施。
示例:- 使用测试数据库进行实验
- 收集测试结果
-
7.3 逐步实施
一旦验证了优化措施的有效性,逐步将其应用于生产环境。
示例:- 先在非高峰时段部署
- 监控效果
-
7.4 效果评估
实施后,再次进行性能测试,评估优化措施的效果,并根据需要继续调整。
示例:- 使用性能监控工具
- 定期复查性能
结论
SQL调优是一个持续的过程,需要不断地监测、分析和调整。通过以上提到的方法,可以有效提升数据库性能,确保应用程序能够平稳运行。在实践中,还需要根据具体的数据库系统、业务需求和技术环境进行灵活调整。
相关文章:
经验笔记:SQL调优
SQL调优经验笔记 引言 SQL调优是确保数据库系统高效运行的重要环节。通过对查询语句、数据库配置、硬件资源等方面进行优化,可以显著提升数据库性能,进而增强应用程序的整体表现。以下是基于常见调优手段和实践经验整理的一份经验笔记。 1. 查询语句优…...

Selenium使用浏览器用户配置进行测试
本文主要介绍了如何在使用Selenium WebDriver进行自动化测试时,创建和使用自定义的Firefox配置文件。 什么是Firefox配置文件? Firefox会将用户的个人信息,如书签、密码和用户偏好设置存储在一个称为配置文件的文件集合中,这些文…...
virsh命令的使用
virsh 是一个用于管理虚拟机的命令行工具,它与 libvirt 服务配合使用,支持对虚拟机的创建、配置、启动、停止等操作。 1、列出虚拟机 列出正在运行的虚拟机: virsh list列出所有虚拟机(包括未启动的): …...

【来学Vue吧】创建一个Vue项目
🌟 嗨,我是命运之光! 🌍 2024,每日百字,记录时光,感谢有你一路同行。 🚀 携手启航,探索未知,激发潜能,每一步都意义非凡。 首先需要配置Vue环境…...
C#迭代器方法和yield用法
一.迭代器方法介绍 可使用foreach循环进行遍历的方法,称为迭代器方法。 迭代器方法使用yield return语句返回元素。 到达yield return语句时,会记住当前在代码中的位置。 下次调用迭代器函数时,将从该位置开始执行。换言之,如果…...
斗破C++编程入门系列之二十六:数组、指针和字符串:动态内存分配和释放(一星斗师)
斗破C目录: 斗破C编程入门系列之前言(斗之气三段) 斗破C编程入门系列之二:Qt的使用介绍(斗之气三段) 斗破C编程入门系列之三:数据结构(斗之气三段) 斗破C编程入门系列之…...
Servlet 和 Spring Boot 的请求处理流程区别和例子
当然可以为您绘制一个流程图,展示 Servlet 和 Spring Boot 的请求处理流程。这将帮助我们更直观地比较两者的工作方式。 #mermaid-svg-PgFEmecUmDhvxxtQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-P…...

C++笔记之map的实用操作
C++笔记之map的实用操作 文章目录 C++笔记之map的实用操作1.初始化1.1.使用列表初始化1.2.使用 `insert` 方法1.3.使用 `emplace` 方法1.4.复制构造1.5.移动构造2.赋值2.1.列表赋值2.2.插入元素2.3.批量插入3.取值3.1.使用 `[]` 操作符3.2.使用 `at()` 方法3.3.检查键是否存在3…...

Lombok失效:报错 找不到符号 Springboot项目
错误原因,Springboot项目为Lombok提供了版本管理的支持,所以引入Lombok依赖的时候,无需手动指定版本,手动指定了可能会导致依赖冲突。 去掉手动指定的版本,问题解决...
Linux 基础命令-文件与目录操作
在 Linux 操作系统中,文件和目录是组织和管理数据的核心单元。作为一个命令行驱动的操作系统,Linux 提供了一系列强大且灵活的命令来操作文件和目录。掌握这些命令不仅是管理 Linux 系统的基础,也是高效使用 Linux 环境的关键。 一、文件与目…...

Delphi 12.1安卓APP开发中获取硬件信息及手机号
Demo与代码已上传到CSDN下载。 这里简单说一下代码内容,完整代码请自行下载,不清楚的欢迎留言交流。 前言 演示Demo使用了我自己开发的一个控件,TLayoutPro 《Delphi D10.3 LayoutsPro 控件简介 -避免输入焦点被虚拟键盘遮挡》请查看并下载控…...
STM32 - 笔记4
1 STM32 示波器 基于STM32的简易示波器项目(含代码)——HAL库_stm32简易示波器 基于STM32的简易示波器项目(含代码)——HAL库_stm32简易示波器_stm32示波器-CSDN博客 【强烈推荐】基于stm32的OLED各种显示实现(含动态图)_stm32oled以十六进制显示-CSDN博客 STM32示波器…...

【H2O2|全栈】更多关于HTML(1)HTML进阶(一)
目录 HTML进阶知识 前言 准备工作 标签的扩展(一) 本文中的标签在什么位置使用? title标签 meta标签 name viewport referrer http-equiv charset content link标签 实际案例 可视部分 代码分析 其他标签 base标签 styl…...

新160个crackme - 053-devilz KeyGen me#3
运行分析 解压出来4个文件运行程序发现要破解Name和Serial PE分析 32位,petite壳 手动脱壳 使用windows XP虚拟机OD打开程序按2下F8,发现ESP变红,根据ESP定律,在该地址右键 -> HW break下断点 继续按2下F9,来到灰色…...

ORA-12514
第一步,去这个地址,查查你的服务名是否存在 第二步,没查到就是你服务名写错了,查到了就退出我的解答...
MyBatis-PlusDruid数据源
MyBatis-Plus简介 MyBatis-Plus(简称MP)是一个MyBatis的增强工具,它在MyBatis的基础上进行了增强而不改变其原有的功能,旨在简化开发、提高效率。以下是对MyBatis-Plus的详细简介: 一、基本概述 定义:MyBat…...

C#中chart绘制曲线
官网资料:Chart 类 (System.Windows.Forms.DataVisualization.Charting) | Microsoft Learn 类的 Chart 两个重要属性是 Series 和 ChartAreas 属性,这两个属性都是集合属性。 Series集合属性存储Series对象,这些对象用于存储要显示的数据以…...

c++数据结构算法题讲解
那么从本期文章开始,会尽量带大家一起刷题 第一题 题目 关键词 思路 源代码 class MinStack { public: void push(int val) { _st.push(val); if(_minst.empty() || val < _minst.top()) { _minst.push(val); } } void pop() { if(_st.top() _minst.top()) {…...
间隙锁在其他数据库管理系统中的类似实现
间隙锁在其他数据库管理系统中的类似实现 一、引言 在 MySQL 中,间隙锁在可重复读事务隔离级别下起到了防止幻读的重要作用。那么在其他数据库管理系统中,是否也有类似的机制来实现类似的功能呢?了解其他数据库管理系统中与间隙锁类似的实现,可以帮助我们更好地理解不同数…...

OpenCV 与 YoloV3的结合使用:目标实时跟踪
目录 代码分析 1. YOLO 模型加载 2. 视频加载与初始化 3. 视频帧处理 4. 物体检测 5. 处理检测结果 6. 边界框和类别显示 7. 帧率(FPS)计算 8. 结果显示与退出 9. 资源释放 整体代码 效果展示 总结 代码分析 这段代码使用 YOLO(…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...