崇左市网站建设_网站建设公司_悬停效果_seo优化
2025/12/17 5:28:44 网站建设 项目流程

1.定位慢SQL

慢查询日志:开启 MySQL 慢查询日志,再通过一些工具比如 mysqldumpslow 去分析对应的慢查询日志,找出问题的根源。

服务监控:可以在业务的基建中加入对慢 SQL 的监控,常见的方案有字节码插桩、连接池扩展、ORM 框架过程,对服务运行中的慢SQL 进行监控和告警。

找到对应的慢 SQL 后,使用 EXPLAIN 命令查看 MySQL 是如何执行 SQL 语句的,这会帮助我们找到问题的根源。

开启MySQL的慢查询日志:

https://blog.csdn.net/m0_74090098/article/details/137639660

2.SQL优化方式

2.1.避免不必要的列

尽量避免select*

2.2.分页优化

数据量巨大时,传统的Limit和offset导致性能不好,数据库扫描需要offset+limit数量的行。

2.2.1.延迟关联

延迟关联适用于需要从多个表中获取数据且主表行数较多的情况。

首先从索引表中检索出需要的行ID,然后再根据这些ID去关联其他的表获取详细信息。

2.2.2.书签

书签方法通过记住上一次查询返回的最后一行的某个值,然后下一次查询从这个值开始,避免了扫描大量不需要的行。

2.3.索引优化

2.3.1.覆盖索引

使用非主键索引查询数据时需要回表,但如果索引的叶节点中已经包含要查询的字段,那就不会再回表查询了,这就叫覆盖索引。

2.3.2.避免使用!<>操纵符

会导致无法使用索引而进行全表扫描。

2.3.3.适当使用前缀索引

适当使用前缀索引可以降低索引空间占用,提高索引查询效率。

前缀索引是指在创建索引时,只对列的前部分字符(而非整个列)进行索引,通常用于 字符串类型的字段,以节省空间并提高查询效率。

创建前缀索引:

CREATE TABLE users (

id INT PRIMARY KEY,

email VARCHAR(255),

INDEX(email(10)) --email字段的前10个字符创建索引

);

在已有表上添加前缀索引:

ALTER TABLE users

ADD INDEX email_prefix_index (email(10));-- 对 email 字段的前 10 个字符创建索引

2.3.4.避免列上使用函数

where子句中直接对列使用函数会导致索引失效,因为数据库需要对每行的列应用函数后再进行比较,无法直接利用索引。

2.3.5.正确使用联合索引

正确地使用联合索引可以极大地提高查询性能,联合索引的创建应遵循最左前缀原则,即索引的顺序应根据列在查询中的使用频率和重要性来安排。

2.4.Join优化

2.4.1.优化子查询

子查询,特别是在 select 列表和 where 子句中的子查询,往往会导致性能问题,因为它们可能会为每一行外层查询执行一次子查询。

例:

SELECT

o.order_id,

o.amount,

(SELECT SUM(amount) FROM orders WHERE customer_id = o.customer_id) AS total_amount

FROM orders o;

※ 对于每一行 orders 表中的记录,都会执行一次内层的子查询 (SELECT SUM(amount) FROM orders WHERE customer_id = o.customer_id)。

2.4.2.小表驱动大表

在执行 JOIN 操作时,应尽量让行数较少的表(小表)驱动行数较多的表(大表),这样可以减少查询过程中需要处理的数据量。

例:

SELECT e.name, d.department_name

FROM employees e

JOINdepartments dONe.department_id = d.id;

employees 表包含的行较少,数据库会首先扫描 employees 表中的所有数据。

对于每一行 employees 表中的数据,数据库会去 departments 表中查找对应的部门信息。由于 departments 表是大表,数据库对它的扫描次数被减少了,因为它只会根据 employees 表中的 department_id 来进行筛选。

2.4.3.适当增加冗余字段

在某些情况下,通过在表中适当增加冗余字段来避免 JOIN 操作,可以提高查询效率,尤其是在高频查询的场景下。

2.4.4.避免join太多表

因为 join 太多表会降低查询的速度,返回的数据量也会变得非常大,不利于后续的处理。

如果业务逻辑允许,可以考虑将复杂的 JOIN 查询分解成多个简单查询,然后在应用层组合这些查询的结果。

2.4.5.利用索引扫描做排序

设计索引时充分考虑排序的需求,这样之后按照索引顺序扫描得到自然有序的结果。

2.5.排序优化(?)

利用索引扫描做排序。

2.6.UNION优化

条件下推是指将 where、limit 等子句下推到 union 的各个子查询中,以便优化器可以充分利用这些条件进行优化。通过将查询条件下推到UNION的每个分支中,每个分支查询都只处理满足条件的数据,减少了不必要的数据合并和过滤。

例:

SELECT id, name, salary FROM employees

WHERE salary > 5000

UNION ALL

SELECT id, name, salary FROM contractors

WHERE salary > 5000;

UNION ALL的作用是将多个查询结果合并为一个结果集,并保留所有重复行,不进行去重。

LIMIT用于限制SQL查询返回的结果行数,常用于分页或只取前几条记录。

3.查看explain

EXPLAIN的作用是显示SQL查询的执行计划,用于分析查询的优化方式和性能瓶颈。

使用方法:在select语句前加explain关键字即可。

①id 列:查询的标识符。

②select_type 列:查询的类型。常见的类型有:

SIMPLE:简单查询,不包含子查询或者 UNION 查询。

PRIMARY:查询中如果包含子查询,则最外层查询被标记为 PRIMARY。

SUBQUERY:子查询。

DERIVED:派生表的 SELECT,FROM 子句的子查询。

③table 列:查的哪个表。

④type 列:表示 MySQL 在表中找到所需行的方式,性能从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL。

system,表只有一行,一般是系统表,往往不需要进行磁盘 IO,速度非常快

const、eq_ref、ref:这些类型表示 MySQL 可以使用索引来查找单个行,其中 const 是最优的,表示查询最多返回一行。

range:只检索给定范围的行,使用索引来检索。在where语句中使用 bettween...and、<、>、<=、in 等条件查询 type 都是 range。

index:遍历索引树读取。

ALL:全表扫描,效率最低。

⑤possible_keys 列:可能会用到的索引,但并不一定实际被使用。

⑥key 列:实际使用的索引。如果为 NULL,则没有使用索引。

⑦key_len 列:MySQL 决定使用的索引长度(以字节为单位)。当表有多个索引可用时, key_len 字段可以帮助识别哪个索引最有效。通常情况下,更短的 key_len 意味着数据库在比较键值时需要处理更少的数据。

⑧ref 列:用于与索引列比较的值来源。

const:表示常量,这个值是在查询中被固定的。例如在 WHERE column = 'value'中。

一个或多个列的名称,通常在 JOIN 操作中,表示 JOIN 条件依赖的字段。

NULL,表示没有使用索引,或者查询使用的是全表扫描。

⑨rows 列:估算查到结果集需要扫描的数据行数,原则上 rows 越少越好。

⑩Extra 列:附加信息。

Using index:表示只利用了索引。

Using where:表示使用了 WHERE 过滤。

Using temporary :表示使用了临时表来存储中间结果。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询