MySQL优化:12种提升SQL执行效率的有效方法

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 在数据库管理和优化的世界里,MySQL作为一个流行的关系型数据库管理系统,其性能优化是任何数据密集型应用成功的关键。优化MySQL数据库不仅可以显著提高SQL查询的效率,还能确保数据的稳定性和可靠性。

在数据库管理和优化的世界里,MySQL作为一个流行的关系型数据库管理系统,其性能优化是任何数据密集型应用成功的关键。优化MySQL数据库不仅可以显著提高SQL查询的效率,还能确保数据的稳定性和可靠性。

本文,已收录于,我的技术网站 ddkk.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享

在本文中,我将介绍12种提升SQL执行效率的有效方法,并通过实用的代码示例来具体展示如何实施这些优化策略。

1、使用索引优化查询

使用场景:当你的数据库表中有大量数据,而你需要频繁进行搜索查询时,索引是提高查询效率的关键。

代码示例

-- 假设我们有一个员工表 employees
CREATE TABLE employees (
    id INT AUTO_INCREMENT,
    name VARCHAR(100),
    department_id INT,
    PRIMARY KEY (id)
);

-- 为department_id字段创建索引
CREATE INDEX idx_department ON employees(department_id);

-- 使用索引进行查询
SELECT * FROM employees WHERE department_id = 5;

代码解释

第一步是创建一个包含id, name, department_id字段的employees表。

然后为department_id字段创建一个索引idx_department。这个操作会让基于department_id的查询更快。

最后,我们执行一个查询,利用创建的索引,从而提高查询效率。

2、优化查询语句

使用场景:避免使用高成本的SQL操作,如SELECT *,尽量指定需要的列,减少数据传输和处理时间。

代码示例

-- 不推荐的查询方式
SELECT * FROM employees;

-- 推荐的查询方式
SELECT id, name FROM employees;

代码解释

第一个查询语句使用了SELECT *,它会获取所有列,这在数据量大时非常低效。

第二个查询仅请求需要的idname列,减少了数据处理的负担。

3、使用查询缓存

使用场景:当相同的查询被频繁执行时,使用查询缓存可以避免重复的数据库扫描。

代码示例

-- 启用查询缓存
SET global query_cache_size = 1000000;
SET global query_cache_type = 1;

-- 执行查询
SELECT name FROM employees WHERE department_id = 5;

代码解释

通过设置query_cache_sizequery_cache_type,我们启用了查询缓存。

当我们执行查询时,MySQL会检查缓存中是否已经有了该查询的结果,如果有,则直接返回结果,避免了重复的数据库扫描。

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。这是大佬写的, 七千页的BAT大佬写的刷题笔记,让我offer拿到手软

4、避免全表扫描

使用场景:当表中数据量巨大时,全表扫描会非常耗时。通过使用合适的查询条件来避免全表扫描,可以显著提高查询效率。

代码示例

-- 假设我们需要查询员工表中特定部门的员工
-- 不推荐的查询方式,会导致全表扫描
SELECT * FROM employees WHERE name LIKE '%张%';

-- 推荐的查询方式
SELECT * FROM employees WHERE department_id = 3 AND name LIKE '%张%';

代码解释

第一个查询使用了模糊匹配LIKE,但缺乏有效的过滤条件,可能导致全表扫描。

第二个查询在name字段的模糊匹配前,增加了对department_id的条件过滤,这样就可以先缩小查找范围,避免全表扫描。

5、使用JOIN代替子查询

使用场景:在需要关联多个表的复杂查询中,使用JOIN代替子查询可以提高查询效率。

代码示例

-- 假设我们有一个部门表 departments
CREATE TABLE departments (
    id INT AUTO_INCREMENT,
    name VARCHAR(100),
    PRIMARY KEY (id)
);

-- 不推荐的子查询方式
SELECT * FROM employees WHERE department_id IN (SELECT id FROM departments WHERE name = 'IT');

-- 推荐的JOIN查询方式
SELECT employees.* FROM employees JOIN departments ON employees.department_id = departments.id WHERE departments.name = 'IT';

代码解释

第一个查询使用了子查询,这在执行时可能效率较低,特别是当子查询或主查询的结果集较大时。

第二个查询使用了JOIN操作,这通常比子查询更有效,尤其是在处理大型数据集时。

6、合理分页

使用场景:在处理大量数据的列表展示时,合理的分页策略可以减少单次查询的负担,提高响应速度。

代码示例

-- 假设我们需要分页显示员工信息
-- 不推荐的分页方式,尤其是当offset值很大时
SELECT * FROM employees LIMIT 10000, 20;

-- 推荐的分页方式,使用更高效的条件查询
SELECT * FROM employees WHERE id > 10000 LIMIT 20;

代码解释

第一个查询使用了LIMIT和较大的偏移量offset,在大数据集上执行时会逐行扫描跳过大量记录,效率低下。

第二个查询通过在WHERE子句中添加条件来避免不必要的扫描,从而提高分页效率。

7、利用分区提高性能

使用场景:对于大型表,特别是那些行数以百万计的表,使用分区可以提高查询性能和数据管理效率。

代码示例

-- 假设我们需要对一个大型的订单表 orders 进行分区
CREATE TABLE orders (
    order_id INT AUTO_INCREMENT,
    order_date DATE,
    customer_id INT,
    amount DECIMAL(10, 2),
    PRIMARY KEY (order_id)
) PARTITION BY RANGE ( YEAR(order_date) ) (
    PARTITION p2020 VALUES LESS THAN (2021),
    PARTITION p2021 VALUES LESS THAN (2022),
    PARTITION p2022 VALUES LESS THAN (2023)
);

-- 查询特定年份的订单
SELECT * FROM orders WHERE order_date BETWEEN '2021-01-01' AND '2021-12-31';

代码解释

我们为orders表创建了基于order_date字段的年份范围分区。

查询特定年份的数据时,MySQL只会在相关分区中搜索,提高了查询效率。

8、利用批处理减少I/O操作

使用场景:在进行大量数据插入或更新时,批处理可以减少数据库的I/O操作次数,从而提高性能。

代码示例

-- 批量插入数据
INSERT INTO employees (name, department_id)
VALUES 
    ('张三', 1),
    ('李四', 2),
    ('王五', 3),
    -- 更多记录
;

-- 批量更新数据
UPDATE employees
SET department_id = CASE name
    WHEN '张三' THEN 3
    WHEN '李四' THEN 2
    -- 更多条件
END
WHERE name IN ('张三', '李四', -- 更多名称);

代码解释

在批量插入示例中,我们一次性插入多条记录,而不是对每条记录进行单独的插入操作。

在批量更新示例中,我们使用CASE语句一次性更新多条记录,这比单独更新每条记录更有效率。

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。这是大佬写的, 七千页的BAT大佬写的刷题笔记,让我offer拿到手软

9、使用临时表优化复杂查询

使用场景:对于复杂的多步骤查询,使用临时表可以存储中间结果,从而简化查询并提高性能。

代码示例

-- 创建一个临时表来存储中间结果
CREATE TEMPORARY TABLE temp_employees
SELECT department_id, COUNT(*) as emp_count
FROM employees
GROUP BY department_id;

-- 使用临时表进行查询
SELECT departments.name, temp_employees.emp_count
FROM departments
JOIN temp_employees ON departments.id = temp_employees.department_id;

代码解释

首先,我们通过聚合查询创建了一个临时表temp_employees,用于存储每个部门的员工计数。

然后,我们将这个临时表与部门表departments进行连接查询,这样的查询通常比直接在原始表上执行复杂的聚合查询要高效。

10、优化数据类型

使用场景:在设计数据库表时,选择合适的数据类型对性能有显著影响。优化数据类型可以减少存储空间,提高查询效率。

代码示例

-- 原始表结构
CREATE TABLE example (
    id INT AUTO_INCREMENT,
    description TEXT,
    created_at DATETIME,
    is_active BOOLEAN,
    PRIMARY KEY (id)
);

-- 优化后的表结构
CREATE TABLE optimized_example (
    id MEDIUMINT AUTO_INCREMENT,
    description VARCHAR(255),
    created_at DATE,
    is_active TINYINT(1),
    PRIMARY KEY (id)
);

代码解释

在原始表中,使用了INTTEXT这样的宽泛类型,这可能会占用更多的存储空间。

在优化后的表中,id字段改为MEDIUMINTdescription改为长度有限的VARCHAR(255)created_at只存储日期,而is_active使用TINYINT(1)来表示布尔值。这样的优化减少了每行数据的大小,提高了存储效率。

11、避免使用函数和操作符

使用场景:在WHERE子句中避免对列使用函数或操作符,可以让MySQL更有效地使用索引。

代码示例

-- 不推荐的查询方式,使用了函数
SELECT * FROM employees WHERE YEAR(birth_date) = 1980;

-- 推荐的查询方式
SELECT * FROM employees WHERE birth_date BETWEEN '1980-01-01' AND '1980-12-31';

代码解释

在第一个查询中,使用YEAR()函数会导致MySQL无法利用索引,因为它必须对每行数据应用函数。

第二个查询直接使用日期范围,这样MySQL可以有效利用birth_date字段的索引。

12、合理使用正规化和反正规化

使用场景:数据库设计中的正规化可以减少数据冗余,而反正规化可以提高查询效率。合理平衡这两者,可以获得最佳性能。

代码示例

-- 正规化设计
CREATE TABLE departments (
    department_id INT AUTO_INCREMENT,
    name VARCHAR(100),
    PRIMARY KEY (department_id)
);

CREATE TABLE employees (
    id INT AUTO_INCREMENT,
    name VARCHAR(100),
    department_id INT,
    PRIMARY KEY (id),
    FOREIGN KEY (department_id) REFERENCES departments(department_id)
);

-- 反正规化设计
CREATE TABLE employees_denormalized (
    id INT AUTO_INCREMENT,
    name VARCHAR(100),
    department_name VARCHAR(100),
    PRIMARY KEY (id)
);

代码解释

在正规化设计中,departmentsemployees表被分开,减少了数据冗余,但可能需要JOIN操作来获取完整信息。

在反正规化设计中,employees_denormalized表通过直接包含部门信息来简化查询,提高读取性能,但可能会增加数据冗余和更新成本。

项目文档&视频:

开源:项目文档 & 视频 Github-Doc

总结

以上提到的优化方法只是众多MySQL优化技术中的一小部分。在实际应用中,应根据具体的数据模式和查询需求灵活选择最合适的优化策略。数据库优化是一个持续的过程,定期的性能评估和调优是保持数据库高效运行的关键。通过实践这些优化技巧,你可以显著提升数据库的性能和响应速度。

本文,已收录于,我的技术网站 ddkk.com,有大厂完整面经,工作技术,架构师成长之路,等经验分享

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6天前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
6天前
|
SQL 缓存 关系型数据库
MySQL高级篇——关联查询和子查询优化
左外连接:优先右表创建索引,连接字段类型要一致、内连接:驱动表由数据量和索引决定、 join语句原理、子查询优化:拆开查询或优化成连接查询
MySQL高级篇——关联查询和子查询优化
|
6天前
|
算法 关系型数据库 MySQL
MySQL高级篇——排序、分组、分页优化
排序优化建议、案例验证、范围查询时索引字段选择、filesort调优、双路排序和单路排序、分组优化、带排序的深分页优化
MySQL高级篇——排序、分组、分页优化
|
6天前
|
存储 关系型数据库 MySQL
MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计
覆盖索引、前缀索引、索引下推、SQL优化、EXISTS 和 IN 的区分、建议COUNT(*)或COUNT(1)、建议SELECT(字段)而不是SELECT(*)、LIMIT 1 对优化的影响、多使用COMMIT、主键设计、自增主键的缺点、淘宝订单号的主键设计、MySQL 8.0改造UUID为有序
MySQL高级篇——覆盖索引、前缀索引、索引下推、SQL优化、主键设计
|
4天前
|
存储 关系型数据库 MySQL
技术解析:MySQL中取最新一条重复数据的方法
以上提供的两种方法都可以有效地从MySQL数据库中提取每个类别最新的重复数据。选择哪种方法取决于具体的使用场景和MySQL版本。子查询加分组的方法兼容性更好,适用于所有版本的MySQL;而窗口函数方法代码更简洁,执行效率可能更高,但需要MySQL 8.0及以上版本。在实际应用中,应根据数据量大小、查询性能需求以及MySQL版本等因素综合考虑,选择最合适的实现方案。
24 6
|
2天前
|
存储 缓存 关系型数据库
MySQL 查询优化方法
在数据库应用中,高效的查询性能至关重要。本文探讨了常用的 MySQL 查询优化方法,包括索引优化(选择合适的索引字段、复合索引、定期维护索引)、查询语句优化(避免全表扫描、限制返回行数、避免使用不必要的函数)、表结构优化(选择合适的数据类型、分区表、定期清理无用数据)及数据库配置优化(调整缓存大小、优化存储引擎参数)。通过这些方法,可以显著提高 MySQL 的查询性能,为应用程序提供更好的用户体验。
|
5天前
|
SQL 监控 关系型数据库
MySQL数据库中如何检查一条SQL语句是否被回滚
检查MySQL中的SQL语句是否被回滚需要综合使用日志分析、事务状态监控和事务控制语句。理解和应用这些工具和命令,可以有效地管理和验证数据库事务的执行情况,确保数据的一致性和系统的稳定性。此外,熟悉事务的ACID属性和正确设置事务隔离级别对于预防数据问题和解决事务冲突同样重要。
18 2
|
8天前
|
SQL 关系型数据库 MySQL
SQL和MySQL
SQL和MySQL
26 1
|
3天前
|
NoSQL 关系型数据库 MySQL
微服务架构下的数据库选择:MySQL、PostgreSQL 还是 NoSQL?
在微服务架构中,数据库的选择至关重要。不同类型的数据库适用于不同的需求和场景。在本文章中,我们将深入探讨传统的关系型数据库(如 MySQL 和 PostgreSQL)与现代 NoSQL 数据库的优劣势,并分析在微服务架构下的最佳实践。
|
5天前
|
存储 SQL 关系型数据库
使用MySQL Workbench进行数据库备份
【9月更文挑战第13天】以下是使用MySQL Workbench进行数据库备份的步骤:启动软件后,通过“Database”菜单中的“管理连接”选项配置并选择要备份的数据库。随后,选择“数据导出”,确认导出的数据库及格式(推荐SQL格式),设置存储路径,点击“开始导出”。完成后,可在指定路径找到备份文件,建议定期备份并存储于安全位置。
65 11