【【Mysql优化】数据库优化方法、Explain使用

news/2024/12/17 2:36:27/

文章目录

      • 一、金字塔优化模型
      • 二、SQL优化的利器:Explain工具
        • 1. Explain 的作用
        • 2. Explain 的用法
      • 三、SQL优化方法(后续文章细讲)
        • 1. 创建索引减少扫描量
        • 2. 调整索引减少计算量
        • 3. 索引覆盖
        • 4. 干预执行计划
        • 5. SQL改写
      • 四、通过 Explain 优化案例
        • 案例1:消除全表扫描
        • 案例2:优化连接查询
      • 五、总结

数据库优化是提高系统性能的关键环节,尤其在面对高并发、大数据量场景时显得尤为重要。优化方法通常呈现“金字塔”结构,从 SQL及索引优化库表结构优化系统配置优化硬件优化,成本逐步提高,而效果逐步减弱。本文将围绕这些优化方法,详细介绍如何通过 Explain 工具分析SQL执行计划,及其在优化中的具体应用。


一、金字塔优化模型

数据库优化方法可以分为以下四个层次:

  1. SQL及索引优化
    • 性价比最高,通过调整查询语句和索引设计即可显著提高性能。
  2. 库表结构优化
    • 通过修改表结构和字段设计,减少冗余或不合理的数据存储。
  3. 系统配置优化
    • 调整数据库缓存、连接池等参数,改善资源分配。
  4. 硬件优化
    • 升级服务器硬件,如扩展内存、增加磁盘I/O吞吐能力。

通常的优化顺序是从下到上,优先选择成本较低的方式。

在这里插入图片描述


二、SQL优化的利器:Explain工具

Explain 是 MySQL 中用于分析查询执行计划的重要工具,可以直观展示查询的执行顺序、索引使用情况等信息。通过 Explain,开发者可以快速定位查询瓶颈,并采取相应优化措施。

1. Explain 的作用
  • 确定表的读取顺序
    确认查询中表与表之间的读取优先级,识别可能存在的顺序问题。
  • 显示查询的访问类型
    分析是否存在全表扫描等低效操作(如 ALL),以便调整索引或优化条件。
  • 分析索引的使用情况
    确定查询可能使用和实际使用的索引,发现未使用索引的情况。
  • 估算扫描的记录行数
    判断查询的影响范围,避免不必要的大量数据扫描。
  • 提供查询额外信息
    例如是否使用了临时表、排序或文件排序等低效操作。
2. Explain 的用法

执行 Explain 查询语句:

sql">EXPLAIN SELECT * FROM users WHERE name = 'John';

在 MySQL 5.7 及之后版本中,Explain 默认返回以下列信息:

列名含义
id查询的标识号,值越大优先级越高
select_type查询类型(如SIMPLEPRIMARYSUBQUERY 等)
table涉及的表名
type查询访问类型(如ALLINDEXRANGE 等,效率从低到高)
possible_keys查询可能使用的索引
key实际使用的索引
rows预估扫描的行数
filtered符合条件的数据百分比
extra查询的额外信息(如Using IndexUsing Filesort 等)

三、SQL优化方法(后续文章细讲)

1. 创建索引减少扫描量

在大表中执行查询时,如果没有索引,通常会进行全表扫描,导致性能低下。通过为查询字段添加索引,可以快速定位数据。例如:

sql">CREATE INDEX idx_name ON users(name);
2. 调整索引减少计算量

优化索引设计,例如使用复合索引,将查询条件中的多个字段合并到一个索引中,可以减少查询计算量。

3. 索引覆盖

索引覆盖是指查询只需从索引中获取数据,而无需回表。例如:

sql">SELECT name FROM users WHERE age > 30;

如果为 age 字段添加索引,并且查询的列仅包括索引字段,则避免了回表查询。

4. 干预执行计划

通过 Explain 提供的执行计划,调整SQL语句或使用提示(Hint)优化执行路径。例如:

sql">SELECT * FROM users FORCE INDEX (idx_name) WHERE name = 'John';

举例说明

假设:

  • orders 表有 100 万条记录,并在 user_id 上有索引。
  • users 表有 10 万条记录,但 status 字段没有索引。

普通 JOIN 查询

sql">EXPLAIN SELECT * FROM orders o JOIN users u ON o.user_id = u.user_id WHERE u.status = 'active';

执行计划可能如下:

idselect_typetabletypepossible_keyskeyrowsExtra
1SIMPLEusersALLNULLNULL100000Using where
2SIMPLEordersrefuser_iduser_id5000
  • 优化器选择了 users 表作为驱动表。
  • 因为 status 没有索引,users 表需要全表扫描。

使用 STRAIGHT_JOIN

sql">EXPLAIN SELECT * FROM orders o STRAIGHT_JOIN users u ON o.user_id = u.user_id WHERE u.status = 'active';

执行计划可能如下:

idselect_typetabletypepossible_keyskeyrowsExtra
1SIMPLEordersrefuser_iduser_id5000
2SIMPLEusersALLNULLNULL500Using where
  • orders 表被优先扫描,通过 user_id 索引减少了扫描量。
  • 关联时,只需要对 users 表的部分记录进行过滤。
5. SQL改写

通过将复杂的SQL拆解为多个简单查询或优化查询条件来提高性能。例如,将嵌套查询改写为关联查询:

改写前

sql">SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE status = 'completed');

改写后

sql">SELECT u.* 
FROM users u
JOIN orders o ON u.id = o.user_id 
WHERE o.status = 'completed';

四、通过 Explain 优化案例

案例1:消除全表扫描

问题:查询执行计划显示 type=ALL,表示全表扫描。
优化:为查询字段创建索引。

sql">-- 优化前
EXPLAIN SELECT * FROM users WHERE name = 'John';-- 优化后
CREATE INDEX idx_name ON users(name);
EXPLAIN SELECT * FROM users WHERE name = 'John';
案例2:优化连接查询

问题:多表关联查询扫描行数过多。
优化:通过复合索引减少关联表的扫描量。

sql">-- 优化前
EXPLAIN 
SELECT u.name, o.order_date 
FROM users u 
JOIN orders o ON u.id = o.user_id;-- 优化后:为连接字段添加索引
CREATE INDEX idx_user_id ON orders(user_id);
EXPLAIN 
SELECT u.name, o.order_date 
FROM users u 
JOIN orders o ON u.id = o.user_id;

五、总结

数据库优化是一项系统性工作,应优先选择成本低、效果好的方式,如 SQL及索引优化Explain 工具作为SQL优化的利器,可以帮助我们分析查询的执行计划,发现性能瓶颈。结合创建索引、调整执行计划、SQL改写等手段,可以大幅提升查询性能。优化并非一次性的工作,而是需要持续监控和调整。


博客主页: 总是学不会.


http://www.ppmy.cn/news/1555746.html

相关文章

分布式 目录

CAP理论 《分布式 & CAP理论 & 总结》《分布式 & CAP理论 & 问题》 分布式事务 《分布式 & 分布式事务 & 总结》《分布式 & 分布式事务 & 问题》 限流算法 《分布式 & 窗口算法 & 总结》《分布式 & 窗口算法 & 问题…

Maven 中的引用与继承:构建项目的得力助手

《Maven 中的引用与继承:构建项目的得力助手》 在 Maven 的奇妙世界里,引用和继承就像是两位神通广大的魔法师,各自施展着独特的魔法,助力我们构建出强大而有序的项目。今天,就让我们一同深入探究这两位魔法师的奥秘吧…

使用open—cv进行图片矫正

实验原理 找到原图 和目标图的四个点,获取透视变换矩阵对图像应用透视变换,实现油画区域的矫正 实验过程 import cv2 import numpy as np# 读取图片文件 img cv2.imread(./g.png)# 定义源图像中的四个角点 points1 np.float32([[174,143],[623,37],…

游戏引擎学习第49天

仓库: https://gitee.com/mrxiao_com/2d_game 回顾 我们当时在讨论我们必须要进行一些改进,以便在游戏中实现更好的碰撞检测。当时展示了一种非常基本的形式,以十字路口为例来实现碰撞交叉工作。然后我们意识到需要升级到更复杂的水平,以便…

【uni-app】App与webview双向实时通信

【uni-app】App与webview双向实时通信 在 Uniapp 中,App 与 里面嵌入的 webview 进行双向的实时通信 vue2 , 模拟器 主要分为两部分 webview 向 app 发送信息 app 向 webview 发送信息 以下是实现方式,用一个例子来说明 (文…

用OpenCV给图像加水印,为图像添加个性

一、引言 在数字时代,保护图片的版权和标识越来越重要。无论是企业的Logo,还是个人作品的水印,都可以有效地标记和保护图像内容。本篇博客将介绍如何使用OpenCV为图片添加水印或Logo。我们将通过简单的代码示例,帮助你快速掌握这…

Debezium OracleDefaultValueConverter 分析

Debezium OracleDefaultValueConverter 分析 目录 1. 概述2. 核心功能3. 类型映射4. 特殊处理5. 最佳实践6. 使用示例7. 总结1. 概述 OracleDefaultValueConverter 是 Debezium Oracle 连接器中负责处理列默认值转换的核心类。它主要用于将 Oracle 数据库中的列默认值转换为 …

Linux系统操作03|chmod、vim

上文: Linux系统操作02|基本命令-CSDN博客 目录 六、chmod:给文件设置权限 1、字母法 2、数字法(用的最多) 七、vim:代码编写和文本编辑 1、启动和退出 1️⃣启动 2️⃣退出 2、vim基本操作 六、chmod&#x…