经验笔记: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(…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
