我是小耶,干运营半路出家的野生DBA——写功课只是为了我踩过的坑,你们别再踩了!
干了快几年,最怕的不是写不出SQL,而是写出来的SQL把数据库干趴了。下面这5个是我自己亲身经历踩过的坑,每个都够牺牲一个半夜。
一、索引失效:明明建了索引,查询还是慢
场景:给order_date字段建了索引,写了一句:
SELECT * FROM orders WHERE DATE(order_date) = '2026-04-23';
结果跑了10秒。为什么?因为对索引列用了函数,数据库只能全表扫描。
常见失效姿势:
- 对索引列做运算:
WHERE price * 1.1 > 100 - 对索引列用函数:
WHERE LEFT(name,3)='abc' - 类型不匹配:
WHERE phone = 13800000000(phone是varchar,没加引号) - 用
OR连接不同列:WHERE id=1 OR name='张三'(只有id有索引)
解决办法:
- 函数或运算,改到等号另一边:
WHERE order_date = '2026-04-23'(不要套DATE) - 类型保持一致,字符串加引号
OR拆成UNION,或者用IN
二、慢查询怎么抓:别等用户投诉才想起来
场景:业务反馈“页面转圈”,你登录数据库一看,CPU 100%,一堆查询跑了几分钟。
正确姿势:
- 提前开慢查询日志
- MySQL设置:
slow_query_log=ON,long_query_time=2(超过2秒记录) - 用
EXPLAIN看执行计划 - 重点看
type列:ALL=全表扫描(要优化),ref/range=用索引了(还行),const=完美。 rows列:预估扫描行数,越大越危险。- 实时抓:
SHOW PROCESSLIST;看哪些查询在跑,KILL掉卡住的。
小技巧:写个脚本每天把慢查询日志发到钉钉/企微,别等半夜被叫醒才看。
三、连表优化:两张大表JOIN,跑了一天没出结果
场景:订单表1000万行,用户表500万行,直接JOIN:
SELECT * FROM orders o JOIN users u ON o.user_id = u.id;
跑崩了。因为MySQL默认用嵌套循环,外层表每一行都要去内层表全扫一遍。
优化手段:
-
先过滤再JOIN
-
用子查询或临时表,把两表各自先缩小范围。
SELECT * FROM (SELECT * FROM orders WHERE order_date >= '2026-01-01') o JOIN (SELECT id,name FROM users WHERE vip_level=3) u ON o.user_id = u.id; -
确保JOIN字段有索引
-
user_id和id必须建索引,否则循环一次扫几百万行。 -
小表驱动大表
-
MySQL优化器通常会选,但你可以用
STRAIGHT_JOIN强制指定顺序。 -
能不JOIN就不JOIN
-
冗余字段有时候比JOIN快。比如订单表直接存
user_name,查的时候就不用连用户表。
四、窗口函数实战:不用它,你还在用临时表算排名?
场景:要算每个分类下销售额前3的产品。没窗口函数时,得写子查询、自连接、用户变量,又长又容易错。
窗口函数一行搞定:
SELECT product_id, category, sales,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS rn
FROM products;
外层套个WHERE rn <= 3,搞定。
常用三个:
ROW_NUMBER():按顺序编号,不重复(1234)RANK():有并列时跳号(1224)DENSE_RANK():并列不跳号(1223)
还有一个实战神技:计算累计占比(帕累托分析)
SELECT product, sales,
SUM(sales) OVER (ORDER BY sales DESC) / SUM(sales) OVER () AS cum_pct
FROM products;
窗口函数是SQL进阶的分水岭。会了,你就能甩开80%的取数员。
五、如何避免删库跑路:手滑是DBA的终身职业病
场景:半夜困得要死,想清空一张临时表,结果连错了库,把生产订单表DELETE了。
血的教训总结:
-
永远先
SELECT再DELETE/UPDATE-- 先看一眼 SELECT * FROM orders WHERE status = '测试'; -- 确认无误,改成DELETE DELETE FROM orders WHERE status = '测试'; -
生产环境关掉自动提交
-
SET autocommit=0;执行完DELETE先SELECT检查影响行数,确认正确再COMMIT。错了就ROLLBACK。 -
养成写
WHERE的好习惯 -
不写
WHERE的DELETE和UPDATE,等于给自己挖坟。 -
区分库
-
用不同颜色背景的客户端连不同环境。生产库用红色主题,测试库用绿色。眼花了还能救一命。
-
备份!备份!备份!
-
定期演练恢复流程。出了事能快速找回数据,比任何预防都管用。
以上每条都是我和同事用熬夜、挨骂、写检讨换来的血泪经验。分享出来,也是为了让更多的人少走点弯路。技术这东西,踩坑不可怕,可怕的是同一个坑踩两次。
如果这5个里面你只能先学一个,我建议先从“避免删库”那节开始。毕竟,保住工作是第一位的。
还有什么关于我运营转码经历你们想了解的,小耶知无不言言无不尽……下次见!