当前位置: 首页 > news >正文

【Java后端】MySQL 常见 SQL 语句优化指南

在 MySQL 中,SQL 优化是性能调优的核心环节,尤其是在数据量大、并发高的情况下。这里整理一份 MySQL 常见 SQL 语句优化指南,从查询写法、索引使用到执行计划分析,涵盖实用技巧:


1. 查询语句层面的优化

✅ 避免 SELECT *

  • 问题:会取出不必要的列,增加 I/O 和网络传输。
  • 优化:只取需要的列。
-- 不推荐
SELECT * FROM user;-- 推荐
SELECT id, username, email FROM user;

✅ 减少子查询,优先使用 JOIN

  • 问题:子查询可能生成临时表,效率低。
  • 优化:能用 JOIN 就不用子查询。
-- 子查询
SELECT name FROM employee WHERE dept_id IN (SELECT id FROM department WHERE name = '研发部'
);-- JOIN 优化
SELECT e.name 
FROM employee e 
JOIN department d ON e.dept_id = d.id
WHERE d.name = '研发部';

✅ 合理使用 LIMIT

  • 问题LIMIT offset, size 偏移量大时性能差。
  • 优化:利用索引字段加条件过滤。
-- 慢
SELECT * FROM orders LIMIT 100000, 20;-- 推荐(基于自增主键优化)
SELECT * FROM orders 
WHERE id > 100000 
LIMIT 20;

✅ 避免 OR,改用 INUNION ALL

  • 问题OR 会导致索引失效。
  • 优化:使用 INUNION ALL
-- 不推荐
SELECT * FROM user WHERE status = 1 OR status = 2;-- 推荐
SELECT * FROM user WHERE status IN (1, 2);

✅ 模糊查询优化

  • 问题LIKE '%abc' 不能走索引。

  • 优化

    • 改写为 LIKE 'abc%'(前缀匹配可以走索引)。
    • 或者使用 全文索引 (FULLTEXT) / ElasticSearch。
-- 慢
SELECT * FROM article WHERE title LIKE '%优化%';-- 推荐
ALTER TABLE article ADD FULLTEXT(title);
SELECT * FROM article WHERE MATCH(title) AGAINST('优化');

✅ 避免在 WHERE 中对列做函数运算

  • 问题:索引失效。
  • 优化:把函数移到等式右边。
-- 不推荐
SELECT * FROM user WHERE YEAR(create_time) = 2024;-- 推荐
SELECT * FROM user 
WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';

2. 索引使用优化

✅ 建立合适的索引

  • 单列索引:适合高频查询字段。
  • 复合索引:遵循 最左前缀原则
CREATE INDEX idx_user_email ON user(email);
CREATE INDEX idx_order_user_time ON orders(user_id, create_time);

✅ 覆盖索引 (Covering Index)

  • 查询字段都在索引中,不需要回表。
-- 索引包含 (user_id, create_time)
SELECT user_id, create_time 
FROM orders 
WHERE user_id = 123;

✅ 避免过多索引

  • 问题:索引会增加写操作开销。
  • 优化:只在查询频繁的字段建索引,删除无用索引。

3. 执行计划分析

✅ 使用 EXPLAIN

分析查询是否走索引。

EXPLAIN SELECT * FROM orders WHERE user_id = 100;

重点关注字段:

  • type:优先级 system > const > eq_ref > ref > range > index > ALL
  • key:实际使用的索引
  • rows:扫描行数,越少越好

4. 表结构与数据优化

  • 分库分表:大表 (>千万行) 考虑拆分。
  • 冷热数据分离:历史数据归档,减少主表数据量。
  • 合理字段类型:能用 INT 不用 BIGINT,能用 CHAR(10) 不用 VARCHAR(255)

5. 常见优化 checklist

  • 是否避免了 SELECT *
  • 是否有合适的索引
  • 是否避免在索引列上使用函数、计算
  • 是否避免大 offset 的分页
  • 是否利用了 EXPLAIN 分析执行计划

http://www.dtcms.com/a/358291.html

相关文章:

  • AI 赋能综合能源管理系统:开启智慧能源新时代
  • 掌握表单:React中的受控组件与表单处理
  • 详解Vue2、Vue3与React的Diff算法
  • 【Android】OkHttp发起GET请求 POST请求
  • React Router 6 获取路由参数
  • 【自然语言处理与大模型】如何进行大模型多模态微调
  • 【ASP.NET Core】双Token机制在ASP.NET Core中的实现
  • OpenCV 图像形态学操作与边缘检测实战指南
  • ESPTimer vs GPTimer:ESP32 定时器系统深度解析
  • 机器学习 - Kaggle项目实践(6)Dogs vs. Cats Redux: Kernels Edition 猫狗二分类
  • 最强分布式锁工具:Redisson
  • Git 的核心工作流程(三区域模型)
  • github同一台电脑支持两个或以上的ssh账户(macos或Linux系统),解决Key is already in use问题
  • 医院排班|医护人员排班系统|基于springboot医护人员排班系统设计与实现(源码+数据库+文档)
  • 苍穹外卖Day7 | 缓存商品、购物车、SpringCache、缓存雪崩、缓存套餐
  • SpringCloud Alibaba微服务--Sentinel的使用
  • docker 部署Skywalking
  • 基于大模型与 PubMed 检索的光谱数据分析系统
  • 大语言模型的“可解释性”探究——李宏毅大模型2025第三讲笔记
  • Java类加载与JVM详解:从基础到双亲委托机制
  • idea 普通项目转换成spring boot项目
  • Python实现半角数字转全角数字的完整教程
  • 《中国棒垒球》垒球世界纪录多少米·垒球8号位
  • Visual Studio(vs)免费版下载安装C/C++运行环境配置
  • LeetCode 287.寻找重复数
  • Java试题-选择题(23)
  • 【LeetCode 热题 100】62. 不同路径——(解法四)组合数学
  • 聊一聊 .NET 的 AssemblyLoadContext 可插拔程序集
  • rhel-server-7.9-x86_64-dvd.iso
  • 机器学习中KNN算法介绍