mysql 优化思路
SELECT *LIKEJOINEXPLAIN下面,我们来详细看看每一部分的具体操作。
优化维度 | 核心思路 | 关键操作/技巧 |
---|---|---|
🔧 索引设计 | 设计高效、合适的索引 | 联合索引与最左前缀、覆盖索引、索引选择性、前缀索引 |
✍️ SQL编写 | 避免索引失效,利用索引 | 避免索引列操作、慎用SELECT * 、LIKE 前缀、JOIN 索引优化 |
🛠️ 维护与工具 | 持续维护与分析 | EXPLAIN 分析、慢查询日志、索引重建 |
下面,我们来详细看看每一部分的具体操作。
🔧 索引设计优化
设计高效且合适的索引是优化查询性能的基石。
-
联合索引与最左前缀原则 创建联合索引时,字段的顺序至关重要。必须遵循最左前缀原则,即查询条件从联合索引的最左列开始。例如,创建
(category_id, comments, views)
的联合索引:-
有效使用索引的查询:
WHERE category_id=1 AND comments>1
、WHERE category_id=1
。 -
无法使用索引的查询:如果跳过
category_id
,直接使用WHERE comments>1
,则该联合索引不会被使用。
-
-
利用覆盖索引 覆盖索引是指一个索引包含了查询所需要的所有字段。它的好处是:
-
避免回表:数据库引擎只需扫描索引即可获取数据,无需根据主键ID再次回表查找,减少I/O操作。
-
提升性能:可以将随机的I/O转变为顺序的I/O,加快查询。 实现方法是在查询中只选取必要的字段,而不是使用
SELECT *
。
-
-
注意索引选择性
-
选择高选择性字段:索引的选择性指索引列中不同值的数量与表记录总数的比例。选择性越高(即不同值越多),索引效率越高。例如,
身份证
字段比性别
字段更适合建索引。 -
避免冗余与重复索引:重复索引(如
primary key(id)
,index(id)
)和冗余索引(如index(a,b,c)
与index(a,b)
)会增加优化器选择负担和存储空间,应避免。
-
-
考虑前缀索引 对于长字符串字段(如
varchar(255)
),如果整个字段建立索引占用空间过大,可以考虑只对字段的前N
个字符建立索引,即前缀索引(例如KEY index(name(20))
)。使用时需要平衡索引大小和查询精度。
✍️ SQL编写优化
SQL优化 1、查询语句中不要使用select * 2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代 3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代 4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好) 5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0
即使有了合适的索引,糟糕的SQL写法也可能导致索引失效。
-
避免索引列操作 在WHERE子句中,应避免对索引列使用函数、计算或类型转换,这会导致索引失效,进行全表扫描。例如,
WHERE YEAR(create_time) = 2024
会导致create_time
上的索引失效。 -
慎用
SELECT \**\*
查询时明确指定需要查询的字段列表**,而不是使用SELECT *
。这样做:-
可以减少网络传输和数据加载的开销。
-
为使用覆盖索引创造了条件。
-
-
LIKE
查询的使用 使用LIKE
进行模糊查询时,前导通配符(如%关键字
)会导致索引失效。尽量使用后导的模糊查询(如关键字%
),这样索引可以有效使用。如果必须使用%关键字%
,可以考虑使用覆盖索引尝试优化。 -
JOIN
关联查询的索引 多表JOIN
时,确保关联字段(ON
后面的条件)上有索引。-
对于
LEFT JOIN
,索引通常建在右表的关联字段上。 -
对于
RIGHT JOIN
,索引通常建在左表的关联字段上。 -
记住一个原则:“小表驱动大表”。
-
🛠️ 维护与工具使用
优化是一个持续的过程,需要借助工具进行分析和定期维护。
-
使用
EXPLAIN
分析执行计划 这是优化慢SQL的核心工具。在SQL语句前加上EXPLAIN
关键字,可以查看MySQL的执行计划,重点关注以下几列:-
type
:表示连接类型,从优到劣常见的有const
、ref
、range
、index
、ALL
(全表扫描)。应尽量避免ALL
。 -
key
:表示实际使用的索引。检查是否使用了预期的索引。 -
rows
:表示预估需要扫描的行数。通常行数越少越好。 -
Extra
:包含额外信息。如果出现Using filesort
(文件排序)或Using temporary
(使用临时表),通常需要优化。
-
-
开启慢查询日志 启用MySQL的慢查询日志功能,可以自动记录执行时间超过指定阈值(如
long_query_time
)的SQL语句。通过定期分析慢查询日志(可以使用mysqldumpslow
或pt-query-digest
等工具),可以系统地发现和定位性能瓶颈。 -
定期维护与索引重建 随着数据频繁增删改,索引会产生碎片,导致性能下降。可以定期执行
OPTIMIZE TABLE table_name
命令来重建索引、整理碎片。
💡 实战优化案例
假设我们有一个 orders
表,并存在这样一条慢查询:
sql
SELECT * FROM orders WHERE customer_id = 12345 ORDER BY order_date DESC LIMIT 10;
优化步骤可能如下:
-
分析:使用
EXPLAIN
分析该SQL,发现type
为ALL
,进行了全表扫描,且Extra
包含Using filesort
。 -
优化索引:考虑查询条件为
customer_id
,排序字段为order_date
,可以创建一个联合索引:ALTER TABLE orders ADD INDEX idx_customer_id_order_date (customer_id, order_date);
。-
这里将等值查询的
customer_id
放在前面,范围查询和排序的order_date
放在后面,符合最左前缀原则且能避免filesort
。
-
-
优化查询:将
SELECT *
替换为具体的字段,例如SELECT order_id, order_amount, ...
,尝试利用覆盖索引进一步减少回表。 -
验证:再次使用
EXPLAIN
分析,确认type
变为ref
或range
,key
显示使用了新索引,并且Using filesort
消失。查询速度应有显著提升。 -
SQL**优化**
1、查询语句中不要使用select *
2、尽量减少子查询,使用关联查询(left join,right join,inner join)替代
3、减少使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
4、or 的查询尽量用 union或者union all 代替(在确认没有重复数据或者不用剔除重复数据时,union all会更好)
5、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。6、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num
is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0
希望这些具体的操作指南能帮助你有效地进行MySQL索引优化!数据库优化是一门实践的艺术,多使用 EXPLAIN
分析,多结合业务场景思考,你就会越来越得心应手。
更多推荐
所有评论(0)