【趣学SQL】第五章:性能优化与调优 5.1 查询性能优化——让数据库跑得比外卖小哥还快的秘籍

第五章:性能优化与调优

5.1 查询性能优化------让数据库跑得比外卖小哥还快的秘籍

欢迎来到「数据库健身房」!今天我们将化身"SQL健身教练",用一家日均处理百万订单的虚拟快递公司崩溃案例,教你如何把龟速查询变成闪电侠。⚡📦


5.1.1 查询性能优化的基本原则------快递公司的"生存法则"

血泪案例

某快递公司未做查询优化导致:

  • 查询某个包裹的物流信息需要8秒(足够快递小哥骑电动车绕办公楼3圈)
  • 促销期间数据库CPU飙到98%(比双十一的快递仓库还热闹)
  • 报表生成耗时2小时(财务小姐姐已经画完三幅简笔画)

黄金三定律

  1. 少搬砖:减少数据扫描量(能用索引绝不扫全表)
  2. 走捷径:利用索引快速定位(像快递分拣机的条形码扫描)
  3. 不返工:避免重复计算(缓存重复使用的中间结果)

📌 行业黑话:执行成本就像快递运费------扫描的行数越多,"运费"越高!


5.1.2 使用 EXPLAIN 分析查询------给SQL做"X光体检"

sql 复制代码
-- 查看包裹查询的执行计划  
EXPLAIN  
SELECT * FROM packages  
WHERE sender_phone = '13812345678'  
  AND create_time > '2023-01-01';  

体检报告解读

+----+-------------+----------+------+---------------+---------+---------+-------+------+-------------+  
| id | select_type | table    | type | possible_keys | key     | key_len | rows  | Extra|  
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------------+  
| 1  | SIMPLE      | packages | ref  | idx_phone     | idx_phone | 66      | 1     | Using where |  
+----+-------------+----------+------+---------------+---------+---------+-------+------+-------------+  

诊断术语表

  • type: ALL(全表扫描→快递员徒步找包裹)、index(索引扫描→骑电动车找)、range(范围扫描→用GPS导航)
  • rows: 预估扫描行数(值越小越好)
  • Extra: Using filesort(需要额外排序→手动整理包裹堆)

5.1.3 优化 WHERE 子句------给查询装上"GPS导航"

反面教材

sql 复制代码
SELECT * FROM packages  
WHERE YEAR(create_time) = 2023 -- 索引失效!  
  AND LEFT(receiver_address, 3) = '北京市'; -- 索引再次阵亡!  

优化方案

sql 复制代码
-- 使用索引友好写法  
SELECT * FROM packages  
WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'  
  AND receiver_address LIKE '北京市%'; -- 最左前缀匹配  

-- 创建联合索引  
CREATE INDEX idx_time_addr ON packages(create_time, receiver_address);  

性能对比

  • 优化前:扫描120万行,耗时4.8秒
  • 优化后:扫描856行,耗时0.02秒

5.1.4 优化 JOIN 操作------多表联动的"高速公路"

车祸现场

sql 复制代码
SELECT *  
FROM orders  
JOIN users ON orders.user_id = users.id  
JOIN products ON orders.product_id = products.id  
WHERE users.city = '上海';  

问题分析

  • 未使用索引导致嵌套循环连接
  • 大表JOIN顺序不合理

优化手段

sql 复制代码
-- 添加索引  
CREATE INDEX idx_user_city ON users(city);  
CREATE INDEX idx_product ON products(id);  

-- 调整JOIN顺序(小表驱动大表)  
SELECT /*+ STRAIGHT_JOIN */  
  orders.*, users.name, products.price  
FROM users  
JOIN orders ON users.id = orders.user_id  
JOIN products ON orders.product_id = products.id  
WHERE users.city = '上海';  

💡 就像让快递小哥先拿小件货,再装大件货更省时间!


5.1.5 优化子查询------解开"俄罗斯套娃"的诅咒

灾难案例

sql 复制代码
SELECT *  
FROM packages  
WHERE id IN (  
  SELECT package_id  
  FROM logistics  
  WHERE status = 'delayed'  
  GROUP BY package_id  
  HAVING COUNT(*) > 3  
);  

执行分析

  • 子查询生成临时表
  • 无法使用索引

优化方案

sql 复制代码
-- 改用JOIN+临时表  
CREATE TEMPORARY TABLE tmp_delayed  
SELECT package_id  
FROM logistics  
WHERE status = 'delayed'  
GROUP BY package_id  
HAVING COUNT(*) > 3;  

SELECT p.*  
FROM packages p  
JOIN tmp_delayed t ON p.id = t.package_id;  

-- 或者使用EXISTS  
SELECT *  
FROM packages p  
WHERE EXISTS (  
  SELECT 1  
  FROM logistics l  
  WHERE l.package_id = p.id  
    AND l.status = 'delayed'  
  GROUP BY l.package_id  
  HAVING COUNT(*) > 3  
);  

5.1.6 优化 GROUP BY 和 ORDER BY------给数据"排队发快递"

低效写法

sql 复制代码
SELECT city, COUNT(*)  
FROM users  
GROUP BY city  
ORDER BY COUNT(*) DESC;  

问题

  • 临时表 + 文件排序

优化技巧

sql 复制代码
-- 利用覆盖索引  
ALTER TABLE users ADD INDEX idx_city (city);  

-- 调整SQL结构  
SELECT city, user_count  
FROM (  
  SELECT city, COUNT(*) AS user_count  
  FROM users  
  GROUP BY city  
) AS tmp  
ORDER BY user_count DESC;  

高级技巧

sql 复制代码
-- 使用索引排序(8.0+支持)  
SELECT province, city, COUNT(*)  
FROM users  
GROUP BY province, city  
ORDER BY province, city;  -- 确保有(province,city)的联合索引  

5.1.7 查询缓存------数据库的"记忆面包"

配置秘籍

sql 复制代码
-- 查看缓存状态  
SHOW VARIABLES LIKE 'query_cache%';  

-- 临时禁用缓存测试真实性能  
SELECT SQL_NO_CACHE * FROM ...  

-- 最佳实践配置(my.cnf)  
query_cache_type = 1  
query_cache_size = 64M  
query_cache_limit = 2M  

适用场景

  • 读多写少的报表查询
  • 重复率高的基础配置查询

失效案例

某论坛开启查询缓存后,每次用户发帖都导致大量缓存失效------就像每次有新快递入库,整个仓库的货物都要重新整理!


课后彩蛋:性能优化冷知识

  • MySQL 8.0废弃了查询缓存功能(因为维护成本太高)
  • 某银行系统曾因ORDER BY RAND()导致每秒20万次全表扫描
  • 最早的数据库优化方式是物理排序磁带来加速查询

现在你已经成为"SQL性能优化大师"!下一章我们将进入《数据库调优------让MySQL跑得比双十一快递还快的终极秘籍》的科幻世界,记得给你的服务器准备氮气加速------查询速度即将突破次元壁! 🚀💨

相关推荐
island13141 小时前
【QT】 控件 -- 显示类
开发语言·数据库·qt
Andya_net2 小时前
网络安全 | F5-Attack Signatures-Set详解
网络·数据库·web安全
码农幻想梦2 小时前
实验二 数据库的附加/分离、导入/导出与备份/还原
数据库·oracle
hillstream33 小时前
Synology 群辉NAS安装(6)安装mssql
数据库·sqlserver
行十万里人生4 小时前
Qt 控件与布局管理
数据库·qt·microsoft·华为od·华为·华为云·harmonyos
betazhou4 小时前
sysbench压力测试工具mysql以及postgresql
数据库·mysql·postgresql
莳花微语4 小时前
OGG 19C 集成模式启用DDL复制
数据库·oracle
潜水的码不二4 小时前
Redis高阶3-缓存双写一致性
数据库·redis·缓存
落霞的思绪4 小时前
Redis实战(黑马点评)——关于缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、Redis工具)
数据库·spring boot·redis·后端·缓存
老苏畅谈运维7 小时前
MySQL性能分析的“秘密武器”,深度剖析SQL问题
数据库·sql·mysql