经验笔记: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(…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...