前言

作为一个写SQL的程序员,代码写得好不好是一回事,但SQL写得烂,性能拉胯,全公司都得为你的慢查询买单,尤其在大数据量表上,SQL写不好就是“内鬼”级别的错误。

今天不整那些虚的,直接来点硬货:20条SQL优化小技巧,每一条都能救你一命,关键是,我还给你配上代码例子,拿去直接用,希望对你会有所帮助。

我最近开源了一个基于 SpringBoot+Vue+uniapp 的商城项目,里面的技术亮点挺多的,欢迎访问和star。[https://gitee.com/dvsusan/susan_mall]

1. 避免SELECT *

别一上来就 SELECT *,你觉得这样写省事,但数据库得把整张表的每一列都给你搬过来,代价大得吓人。需要啥列写清楚,别偷懒。

-- 错误写法
SELECT * FROM users; -- 正确写法
SELECT id, name, age FROM users;

优化原因:减少网络传输数据量,避免无用字段占内存。

最后说一句(求关注,别白嫖我)

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下我的同名公众号:苏三说技术,您的支持是我坚持写作最大的动力。

求一键三连:点赞、转发、在看。

关注公众号:【苏三说技术】,在公众号中回复:进大厂,可以免费获取我最近整理的10万字的面试宝典,好多小伙伴靠这个宝典拿到了多家大厂的offer。

2. WHERE字段要有索引

你写 WHERE 条件时,涉及到的字段要有索引。没索引,MySQL 就得一行行地扫描表,全表扫描慢得你怀疑人生。

-- 创建索引
CREATE INDEX idx_users_age ON users(age); -- 使用索引查询
SELECT * FROM users WHERE age > 25;

优化原因:索引就像目录,能直接跳到你要的那页,而不是一本书从头翻到尾。

3. 用EXPLAIN分析SQL性能

写SQL前,别直接跑,先加个 EXPLAIN 看看执行计划。看啥?type 是不是 ALL,是不是走了全表扫描。如果有,赶紧改。

EXPLAIN SELECT * FROM users WHERE age > 25;

优化原因:清楚执行计划,知道SQL跑得是不是高效。

4. 避免WHERE里的函数操作

别在WHERE条件里对字段用函数,索引直接失效。

-- 错误写法
SELECT * FROM users WHERE YEAR(create_time) = 2023; -- 正确写法
SELECT * FROM users WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01';

优化原因:函数操作让索引失效,回表扫描浪费时间。

5. 避免OR条件,改用UNION

WHERE 里写了个 OR,可能导致两个字段的索引全失效。别用 OR,用 UNION 替代。

-- 错误写法
SELECT * FROM users WHERE age = 25 OR city = 'shenzhen'; -- 正确写法
SELECT * FROM users WHERE age = 25
UNION
SELECT * FROM users WHERE city = 'shenzhen';

优化原因:OR 会让索引失效,而 UNION 可以分别利用索引。

6. 优化LIMIT分页

LIMIT 用得好不好直接影响性能,特别是分页到 10000 页的时候,直接卡死你。改进方法是用 ID 或时间范围过滤。

-- 错误写法
SELECT * FROM users ORDER BY create_time LIMIT 10000, 10; -- 正确写法
SELECT * FROM users WHERE id > 10000 ORDER BY id LIMIT 10;

优化原因:用范围过滤减少不必要的扫描。

7. 用覆盖索引

覆盖索引的意思是,查询的字段全在索引里,MySQL 不需要回表。

-- 创建覆盖索引
CREATE INDEX idx_users_age_name ON users(age, name); -- 查询
SELECT name FROM users WHERE age > 25;

优化原因:只从索引获取数据,不用回表,提高查询速度。

8. 减少JOIN表数量

JOIN 太多表会让执行计划复杂化,数据量大的表用 JOIN,性能就拉了。

-- 复杂的多表JOIN
SELECT * FROM orders
JOIN users ON orders.user_id = users.id
JOIN products ON orders.product_id = products.id; -- 优化:拆分查询
SELECT * FROM orders WHERE user_id IN (
SELECT id FROM users WHERE age > 25
);

优化原因:减少中间表的数据处理量,降低JOIN复杂度。

9. 使用批量插入

单条插入写多了,性能会被写锁拖垮,换成批量插入。

-- 错误写法
INSERT INTO users (id, name) VALUES (1, 'zhangsan');
INSERT INTO users (id, name) VALUES (2, 'lisi'); -- 正确写法
INSERT INTO users (id, name) VALUES (1, 'zhangsan'), (2, 'lisi');

优化原因:减少数据库连接和提交的次数。

10. GROUP BY前过滤数据

GROUP BY 本质上是对结果排序分组,数据量大时效率感人。先用 WHERE 把数据量缩小。

-- 错误写法
SELECT age, COUNT(*) FROM users GROUP BY age; -- 正确写法
SELECT age, COUNT(*) FROM users WHERE age > 25 GROUP BY age;

优化原因:减少GROUP BY处理的数据量。

11. LIKE查询优化

模糊查询用 %xxx% 的时候,索引没了,直接全表扫描。改成前缀匹配,或者用全文索引。

-- 前缀匹配
SELECT * FROM users WHERE name LIKE 'zhang%'; -- 全文索引
CREATE FULLTEXT INDEX idx_name ON users(name);
SELECT * FROM users WHERE MATCH(name) AGAINST('zhang');

优化原因:用索引提高查询效率。

12. 避免大字段频繁查询

TEXT 和 BLOB 这种大字段会拖累查询性能,把它们单独拆到一张表。

-- 原表
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50),
profile TEXT
); -- 拆表
CREATE TABLE user_profiles (
user_id INT PRIMARY KEY,
profile TEXT
);

优化原因:减少主表查询时的大字段负担。

13. 定期清理无用数据

表里垃圾数据太多,索引也跟着膨胀,查询性能直线下降。

-- 定期清理历史数据
DELETE FROM logs WHERE create_time < '2022-01-01';

优化原因:保持表轻量化,避免数据膨胀。

14. 用分区表优化大数据表

分区表是大数据量优化的利器,把数据按范围分成多个分区。

CREATE TABLE orders (
id INT NOT NULL,
order_date DATE NOT NULL
) PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2022 VALUES LESS THAN (2023),
PARTITION p2023 VALUES LESS THAN (2024)
);

优化原因:查询只扫描一个分区,而不是整张表。

15. 索引字段选用低基数的字段

基数低的字段(比如性别)用索引没意义,能用组合索引就用。

-- 错误:性别字段加索引
CREATE INDEX idx_gender ON users(gender); -- 正确:性别+年龄组合索引
CREATE INDEX idx_gender_age ON users(gender, age);

优化原因:避免低基数索引浪费存储。

16. 控制表字段数量

表字段太多会让数据表臃肿,查询性能也会变差。合理拆分表。

17. 用事务优化批量更新

大批量更新用事务,可以减少锁竞争。

START TRANSACTION;
UPDATE users SET age = age + 1 WHERE age > 25;
COMMIT;

18. 用查询缓存

MySQL 有查询缓存机制,适合静态数据高频查询场景。

-- 开启查询缓存
SET GLOBAL query_cache_size = 1048576;
SELECT SQL_CACHE * FROM users WHERE age > 25;

19. 用PreparedStatement

预编译可以提高性能,还能防止 SQL 注入。

20. 定期优化表

表用了很久会有碎片,定期优化表能提高性能。

OPTIMIZE TABLE users;

总结

SQL 优化是个手艺活,写好 SQL 就能少掉无数锅,尤其是团队开发时,一个烂 SQL 能拖死整个项目。

这 20 条技巧别只看一遍,拿着自己的查询多实践,别等线上掉链子才后悔!

SQL优化的20条军规的更多相关文章

  1. Yahoo前端优化的35条军规

    摘要:无论是在工作中,还是在面试中,web前端性能的优化都是很重要的,那么我们进行优化需要从哪些方面入手呢?可以遵循雅虎的前端优化34条军规,不过现在已经是35条了,所以可以说是雅虎前端优化的35条军 ...

  2. Oracle SQL性能优化的40条军规

    1. SQL语句执行步骤 语法分析> 语义分析> 视图转换 >表达式转换> 选择优化器 >选择连接方式 >选择连接顺序 >选择数据的搜索路径 >运行“执 ...

  3. MySQL性能优化的20条经验

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数 ...

  4. MySQL性能优化的20+条经验

    1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...

  5. Yahoo关于性能优化的N条军规

    一. Yahoo的军规条例: 谨记:80%-90%的终端响应时间是花费在下载页面中的图片,样式表,脚本,flash等:详细的解释来这里查:http://developer.yahoo.com/perf ...

  6. 基于Yahoo网站性能优化的34条军规及自己的见解

    1.尽量减少HTTP请求次数 终端用户响应的时间中,有80%用于下载各项内容,这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数,这是提高网页速 ...

  7. 雅虎(yahoo)前端优化十四条军规

    第一条.尽可能的减少 HTTP 的请求数 (Make Fewer HTTP Requests ) http请求是要开销的,想办法减少请求数自然可以提高网页速度.常用的方法,合并css,js(将一个页面 ...

  8. Yahoo前端优化十四条军规

    相信互联网已经越来越成为人们生活中不可或缺的一部分.Ajax,flex等等富客户端的应用使得人们越加“幸福”地体验着许多原先只能在C/S实 现的功能. 比如Google机会已经把最基本的office应 ...

  9. Yahoo网站性能优化的34条军规

    1.尽量减少HTTP请求次数 终端用户响应的时间中,有80%用于下载各项内容,这部分时间包括下载页面中的图像.样式表.脚本.Flash等.通过减少页面中的元素可以减少HTTP请求的次数,这是提高网页速 ...

  10. Python性能优化的20条建议 (转载)

    优化算法时间复杂度 算法的时间复杂度对程序的执行效率影响最大,在Python中可以通过选择合适的数据结构来优化时间复杂度,如list和set查找某一个元素的时间复杂度分别是O(n)和O(1).不同的场 ...

随机推荐

  1. Three.js入门-常见几何体

    这章节,我们将介绍 Three.js 中常见的几何体(Geometry),包括立方体.球体.圆柱体.平面.圆环.圆锥体等.几何体是构建 3D 模型的基础元素,通过不同的几何体可以创建出各种形状的物体. ...

  2. 面试官:来谈谈Vue3的provide和inject实现多级传递的原理

    前言 没有看过provide和inject函数源码的小伙伴可能觉得他们实现数据多级传递非常神秘,其实他的源码非常简单,这篇文章欧阳来讲讲provide和inject函数是如何实现数据多级传递的.ps: ...

  3. 推进国产化安全应用:德承工控机DV-1100+银河麒麟操作系统Kylin V10 安装教程

    银河麒麟操作系统 V10是一款适配国产软硬件平台并深入优化和创新的新一代图形化桌面操作系统,支持国内外多款主流的处理器,飞腾.鲲鹏.海思麒麟.龙芯.申威.海光.兆芯等国产CPU和Intel.AMD等平 ...

  4. 《JavaScript 模式》读书笔记(6)— 代码复用模式1

    我们有开始进入新篇章了.这篇内容主要讲代码复用模式,实际上代码复用,就是继承啊,原型啊,构造函数啊等等这一类的内容.对于前端进阶来说,是很重要的基础知识.这一篇内容会对原型. 继承有很深入的讲解.我也 ...

  5. jsp移动端和pc端页面判断及切换

    function goPAGE() { if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobi ...

  6. VLC web(http)控制 (2) 状态获取

    VLC 状态通过http://127.0.0.1:8080/requests/status.xml获取.(IP地址自行更换) 内容如下: <root> <fullscreen> ...

  7. ArkTs布局入门04——相对布局 & 媒体查询

    1.相对布局 1.1.概述 RelativeContainer为采用相对布局的容器,支持容器内部的子元素设置相对位置关系.子元素支持指定兄弟元素作为锚点,也支持指定父容器作为锚点,基于锚点做相对位置布 ...

  8. 禅道bug增加自定义字段

    禅道版本 18.9 需求 给禅道的bug模块,增加自定义字段. 目前主要增加"发现阶段"."所属环境"."出现频率" 增加bug的类型 在b ...

  9. Javadoc 使用详解

    很多程序对Javadoc都不重视,认识不到Javadoc的作用,很多人都是这样认为的:"我只要写好功能就够了,写Javadoc太浪费时间,也没啥作用,还不如用写Javadoc的时间再多些个功 ...

  10. Qt编写安防视频监控系统49-多数据库支持

    一.前言 数据库设置模块,因为很多项目都会用到,索性这期间也将这玩意重新架构了一遍,对应的数据库组件同样重写了一遍,关于数据库的参数无非就6个,数据库类型(sqlite.mysql等).数据库名称.主 ...