LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

8 个最容易写错的 SQL 习惯,正在拖慢并毁掉你的数据库

admin
2026年4月13日 22:35 本文热度 12

很多数据库问题,并不是“高并发架构”这种听起来很吓人的大场面搞出来的。

真正把库拖慢、把业务搞崩、把同事逼疯的,往往是一些看起来没什么问题、实际上非常致命的 SQL 习惯

这些写法在测试环境里也许还能跑,在数据量小的时候也许没感觉,但一旦表变大、业务变复杂、并发上来,代价就会立刻显现:慢查询、锁表、索引失效、脏数据、误删、甚至直接事故

今天就来聊 8 个最常见、也最容易被忽视的坏习惯。

如果你平时写 SQL,这篇建议你对照着自查一遍。


1. 张口就是 SELECT *

这是最常见的“偷懒型写法”。

SELECT *
FROM
 orders
WHERE
 user_id = 1001;

看上去很方便,但问题不少:

  • • 读取了根本不需要的列,增加 IO 和网络传输
  • • 表结构一变,应用层可能跟着炸
  • • 更难命中覆盖索引
  • • 联表时尤其容易把数据量拉爆

更稳妥的写法是:只查你真正需要的字段。

SELECT order_id, order_no, total_amount, created_at
FROM
 orders
WHERE
 user_id = 1001;

为什么这件事很重要?

因为数据库的性能问题,很多时候不是“算得太慢”,而是“搬得太多”。

你以为自己只是多拿了几列,数据库看到的是:

  • • 更多页读取
  • • 更大结果集
  • • 更重排序/回表成本
  • • 更差缓存命中率

一句话: 是小项目的朋友,大表时代的敌人。


2. WHERE 条件对字段做函数运算

很多人写条件时,喜欢直接对列做处理:

SELECT *
FROM
 orders
WHERE
 DATE(created_at) = '2026-03-26';

这类写法语义上没错,但性能上很容易出事。

因为当你对索引列做函数计算时,数据库往往没法直接利用索引,最后就可能退化成全表扫描。

更好的写法是改成范围查询:

SELECT order_id, user_id, created_at
FROM
 orders
WHERE
 created_at >= '2026-03-26 00:00:00'
  AND
 created_at <  '2026-03-27 00:00:00';

记住一个简单原则

尽量别动列,去动常量。

也就是说,别让数据库先把每一行都加工一遍,再比较;而是把边界算好,直接去命中索引。

这类错误在以下场景尤其常见:

  • • DATE(create_time)
  • • YEAR(order_time)
  • • SUBSTRING(phone, 1, 3)
  • • UPPER(name)

看着优雅,跑起来经常像灾难片。


3. 模糊查询一上来就是前缀 %

比如:

SELECT *
FROM
 users
WHERE
 name LIKE '%周%';

这类查询在搜索场景很常见,但一旦前面加了 %,普通索引通常就很难用了。

结果就是:扫全表,然后一行一行比。

如果你的表有几百万数据,这种写法就不再是“能跑”,而是“谁写的,出来挨打”。

怎么改?

要看业务目标:

情况一:前缀匹配

SELECT user_id, name
FROM
 users
WHERE
 name LIKE '周%';

这种更有机会走索引。

情况二:全文搜索需求

如果你真的是要“包含某关键词”,别硬拿普通 LIKE '%xxx%' 扛所有搜索需求。

更合理的方向通常是:

  • • 全文索引
  • • 搜索引擎(如 Elasticsearch)
  • • 额外搜索字段 / 倒排方案

数据库不是不能搜,但你别拿它当全文检索引擎往死里打。


4. INOR、联表条件乱写,结果把执行计划写崩了

很多 SQL 慢,不是因为数据库不够强,而是因为你把优化器逼疯了。

例如:

SELECT *
FROM
 orders
WHERE
 status = 'PAID'
   OR
 user_id = 1001;

再比如:

SELECT *
FROM
 orders
WHERE
 id IN (1,2,3,4,5,...一大串...);

或者联表时条件不清晰:

SELECT *
FROM
 orders o
JOIN
 users u ON o.user_id = u.id
WHERE
 o.created_at >= '2026-01-01';

表面看都合法,实际上可能导致:

  • • 走不上理想索引
  • • 连接顺序变差
  • • 中间结果集过大
  • • CPU 飙升

更靠谱的思路

  • • 大量 IN 值,考虑临时表 / 批量表驱动
  • • OR 条件复杂时,考虑拆成 UNION ALL
  • • 联表前先过滤小结果集
  • • 别默认“SQL 能运行 = SQL 写得对”

例如把 OR 拆开:

SELECT order_id, user_id, status
FROM
 orders
WHERE
 status = 'PAID'

UNION
 ALL

SELECT
 order_id, user_id, status
FROM
 orders
WHERE
 user_id = 1001
  AND
 status <> 'PAID';

不一定每次都要这么写,但你至少得知道:

复杂条件不是不能写,而是不能闭着眼乱写。


5. 分页永远只会写 LIMIT 100000, 20

这也是经典事故现场。

SELECT *
FROM
 orders
ORDER
 BY id
LIMIT 100000, 20;

在前期数据少的时候没什么感觉,数据一多就开始痛了。

原因很简单:数据库不是直接跳到第 100000 行给你拿 20 条,它通常需要先扫描/排序前面大量记录,再丢掉它们

页码越深,越慢。

更好的方式:游标分页 / 基于最后一条记录翻页

SELECT order_id, id, created_at
FROM
 orders
WHERE
 id > 100000
ORDER
 BY id
LIMIT 20;

如果按时间 + ID 排序,也可以这样:

SELECT order_id, created_at
FROM
 orders
WHERE
 (created_at, id) > ('2026-03-26 08:00:00', 100000)
ORDER
 BY created_at, id
LIMIT 20;

什么时候还能用 offset 分页?

可以,但要有边界:

  • • 后台管理系统
  • • 数据量不大
  • • 只翻前几页

一旦是开放式列表、大数据量、用户不断下拉,继续死磕深分页,就是在给数据库加班。


6. UPDATE / DELETE 不带条件,或者条件写得过于自信

这个不用解释太多,懂的都疼。

DELETE FROM orders;

或者:

UPDATE users
SET
 status = 'inactive';

有些人会说:“我不是不加条件,我只是条件写错了。”

那效果也没什么本质区别。

更稳的操作习惯

先查再改

SELECT *
FROM
 users
WHERE
 last_login_at < '2025-01-01';

确认影响范围没问题,再执行:

UPDATE users
SET
 status = 'inactive'
WHERE
 last_login_at < '2025-01-01';

先加 LIMIT(适用于支持的场景)

DELETE FROM logs
WHERE
 created_at < '2024-01-01'
LIMIT 1000;

在事务里执行,并先备份关键数据

尤其是生产环境,别把自己当赌神。

一个建议,虽然朴素但管用

凡是会改数据的 SQL,执行前都问自己一句:

“如果我这句条件写错了,最坏会死多少数据?”

你会立刻冷静很多。


7. 觉得“有索引就一定快”,结果建了一堆废索引

不少团队一遇到慢 SQL,就开始下意识加索引。

这思路和“头疼就把头砍了”差不多,主打一个直接。

问题是,索引不是免费午餐。

索引会带来:

  • • 额外存储开销
  • • 插入、更新、删除变慢
  • • 优化器选择更复杂
  • • 重复索引、冗余索引越来越多

例如下面这种:

  • • 索引 A:(user_id)
  • • 索引 B:(user_id, status)
  • • 索引 C:(user_id, status, created_at)

很多时候你以为自己很细致,实际上是在堆垃圾。

正确姿势是什么?

  • • 根据实际查询模式建索引
  • • 看执行计划,不靠想象优化
  • • 关注联合索引最左前缀原则
  • • 定期清理重复 / 冗余索引

一句话:

索引是手术刀,不是护身符。


8. 不看执行计划,纯靠玄学调 SQL

这是最致命的习惯。

很多人优化 SQL 的方式是这样的:

  • • “我感觉这个会快一点”
  • • “网上有人这么写”
  • • “我把子查询改成联表了,应该高级一点”
  • • “我加了个索引,信仰已经到位”

问题是,数据库不看你的感觉,只看执行计划。

优化 SQL,至少先看这些

以 MySQL 为例,先跑:

EXPLAIN
SELECT
 order_id, user_id, total_amount
FROM
 orders
WHERE
 user_id = 1001
  AND
 created_at >= '2026-03-01 00:00:00';

重点关注:

  • • type:访问类型是不是太差
  • • key:到底用了哪个索引
  • • rows:预估扫描多少行
  • • Extra:有没有 Using filesortUsing temporary

如果连执行计划都不看,就开始“优化”,那基本等于:

闭着眼给数据库做手术。

勇气可嘉,结果一般不太行。


最后总结:真正毁库的,往往不是复杂 SQL,而是习惯性随手一写

把今天这 8 条收一下:

  1. 1. SELECT * 随手乱用
  2. 2. 在索引列上做函数运算
  3. 3. 模糊查询前缀直接 %
  4. 4. OR / IN / 联表条件乱写
  5. 5. 深分页只会用 LIMIT offset, size
  6. 6. UPDATE / DELETE 过于自信
  7. 7. 乱加索引,把数据库当收纳箱
  8. 8. 不看执行计划,靠玄学调优

这些问题有一个共同点:

平时不痛,一出事就很痛。

而且最可怕的是,它们几乎都不是“不会 SQL”造成的,反而经常出现在“会一点、写得很顺手”的阶段。

真正靠谱的 SQL 开发习惯,不是能把语法写对,而是:

  • • 知道数据库怎么想
  • • 知道索引什么时候失效
  • • 知道哪种写法在数据量上来后会翻车
  • • 知道每一条改数据语句都可能有后果


阅读原文:原文链接


该文章在 2026/4/14 16:17:42 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号