MySQL性能优化7个冷知识,看完少踩3年坑

MySQL优化是老话题了,但很多工程师搞了很久还是在重复踩同样的坑。这篇整理7个实战中容易忽略的细节,助你一次性把性能提上去。

1. 索引不是越多越好

很多人觉得”查慢就加索引”,结果表里有十几条索引,写性能严重下降。索引是一把双刃剑:读加速,写变慢。每增加一个索引,INSERT/UPDATE都要维护对应B+树。原则:单表索引不超过5个,只给WHERE/ON条件字段建索引。

2. LIKE前面不能加%

-- 失效:LIKE以通配符开头,索引无法命中
SELECT * FROM orders WHERE order_no LIKE '%2026%';

-- 生效:LIKE以具体值开头
SELECT * FROM orders WHERE order_no LIKE '2026%';

-- 如果必须前缀匹配,用Redis或ES替代MySQL

3. COUNT(*) 和 COUNT(1) 性能一样?

在InnoDB中,COUNT(*)需要扫描全表或索引来获取行数,COUNT(1)本质上一样。真正快的方案:建一个单独的计数字段,用触发器或应用层维护。适用于频繁需要COUNT的场景(如帖子评论数)。

4. 慢查询日志不是摆设

-- 开启慢查询日志(生产环境建议持续开启)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;

-- 用EXPLAIN分析(重点看type/key/rows)
EXPLAIN SELECT * FROM orders WHERE status = 'paid';

5. 联合索引遵守最左前缀原则

-- 建了联合索引 (status, created_at, user_id)

-- 能命中索引:
WHERE status = 'paid' AND created_at > '2026-01-01'  -- 命中
WHERE status = 'paid'                                    -- 命中

-- 不能命中索引:
WHERE created_at > '2026-01-01'  -- 跳过status,无法命中

6. JOIN记得指定驱动顺序

MySQL优化器不总是选对JOIN顺序。用STRAIGHT_JOIN强制指定JOIN顺序,小表在前、大表在后:

SELECT * FROM large_orders o
STRAIGHT_JOIN users u ON o.user_id = u.id
STRAIGHT_JOIN products p ON o.product_id = p.id;
-- large_orders(数据最多)放在最前面,驱动它扫描一次即可

7. 批量插入用LOAD DATA INFILE

-- 普通INSERT:每条单独commit,网络往返开销大
INSERT INTO orders VALUES (1,'A'),(2,'B');  -- 1000条=1000次网络

-- LOAD DATA:文件级导入,速度快10-50倍
LOAD DATA LOCAL INFILE '/tmp/orders.csv'
INTO TABLE orders
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\\n';

-- 数据量大时,先禁用索引再重建
ALTER TABLE orders DISABLE KEYS;
LOAD DATA ...
ALTER TABLE orders ENABLE KEYS;

总结

知识点 核心要点
索引不是越多越好 单表不超过5个索引,读快写慢
LIKE前加%失效 前缀匹配才能命中索引
COUNT性能 InnoDB全表扫描,考虑计数字段
慢查询日志 生产环境持续开启,EXPLAIN分析
最左前缀原则 联合索引从左到右使用,不能跳过中间
JOIN顺序 小表驱动大表,大表在前用STRAIGHT_JOIN
批量插入 LOAD DATA INFILE比INSERT快10-50倍

MySQL优化没有捷径,但方向对了就不怕路远。慢查询日志+EXPLAIN是标配,索引合理化是根本,架构层面的读写分离和分库分表是大招。

⚠️ 声明:本文相关内容仅供参考。

发表评论

苏ICP备18039580号-2