-
我图省事把上万个 ID 一股脑塞进 SQL 的 WHERE id IN (...) 里去批量查询、小批量测的时候快得飞起,结果生产环境列表一大这条查询就慢成狗有时还直接报参数过多的错、DBA 看监控说这一条 SQL 把库都拖垮了,排查很久才搞懂一个在小规模下完美的 IN 写法放大到上万个值时会在解析执行计划缓存好几个地方同时崩坏的深度复盘
我有个需求要根据一批 ID 去数据库批量查记录、写得特别直白把所有 ID 拼进一个 IN 列表 SELECT * FROM orders WHERE id IN (1,2,3,...上万个)。开发测试时手头 ID 也就几十个查询飞快毫无问题顺利上线。可生产环境:某些场景 ID 列表上万个这条查询慢得离谱从毫秒飙到几秒十几秒、而同样表查单条飞快;某些数据库上 IN 列表超过某数量直接报错参数太多/表…- 2
- 0
-
我写了个 SQL 想查出状态为空的记录、用了 WHERE status = NULL,结果一行都查不出来,我又写了个 NOT IN 子查询,这次更怪、整个结果集凭空变成了空,排查半天才明白 SQL 里的 NULL 根本不能用等号去比的深度复盘
我有张表有些记录的 status 是空(NULL),想把状态为空的记录查出来,很自然写了 WHERE status = NULL。可结果一行都没返回,哪怕表里明明有一堆 status 为 NULL 的记录。我以为数据问题,查全表那些 NULL 记录清清楚楚在。又想查 status 不在某列表里的记录,写了 NOT IN 子查询,结果更诡异:整个结果集凭空变空。直到补了 SQL 对 NULL 的处理…- 0
- 0
-
一条 NOT IN 子查询的 SQL,因为子查询里混进了一个 NULL,把本该返回几千行的结果集变成了空,我栽进了 SQL 三值逻辑的坑:一次 NULL 处理的深度复盘
想查所有从没被订单引用过的商品,WHERE id NOT IN (SELECT product_id FROM orders),本该返回几千行却返回空、还不报错。根因是子查询的 product_id 列里混进了 NULL:SQL 是三值逻辑(TRUE/FALSE/UNKNOWN),NULL 表示未知、任何和它的比较都得 UNKNOWN,id NOT IN(含 NULL)等价于 ...AND id!…- 2
- 0
-
我写了个查询所有非 active 用户的 SQL,结果状态为 NULL 的用户竟然一个都没查出来,报表数据莫名少了一大截,我对着 SQL 里 NULL 参与比较结果是 UNKNOWN 这个三值逻辑坑排查大半天的复盘
一个让我对 SQL 里的 NULL 彻底改观的坑,诡异在查询条件逻辑上看完全正确(查所有 status 不是 active 的用户),返回结果却悄悄漏掉了一部分本该符合的数据,而漏的正是 status 为 NULL 的行,这种静默漏数据在报表里尤其致命。用户表 status 有 active、inactive 和一些 NULL,我写 SELECT * FROM users WHERE status…- 0
- 0
-
我用 NOT IN 子查询过滤数据,结果返回了空集、明明该有很多行,还有个 != 查询莫名其妙漏了一批数据,我对着 SQL 里 NULL 的三值逻辑排查了大半天的复盘
两段普通 SQL:一段 NOT IN 子查询排除用户,一段 WHERE status != active 查非活跃用户。结果诡异:NOT IN 那段明明该返回一大批却返回空集;!= 那段查出的非活跃用户竟漏掉了一批 status 为 NULL 的(它们明明也不是 active)。盯着 SQL 反复看逻辑没毛病甚至怀疑是数据库 bug,排查大半天才理解让无数人栽跟头的概念——NULL 的三值逻辑:N…- 0
- 0
-
我用不等于条件查"未完成"的订单,结果一批 status 为 NULL 的订单全被漏掉了、数量怎么都对不上,我对着 SQL 的三值逻辑排查了大半天的复盘
我用 WHERE status != 'done' 查所有未完成订单,对账却数量对不上——所有被漏掉的订单 status 都是 NULL。NULL 明明不等于 done,为什么 != 'done' 没把它们选出来?深挖才懂是 SQL 的三值逻辑:NULL 表示"未知",拿它和任何值比较(=、!=、>、甚至 = NULL)结果都不是 …- 0
- 0
-
一条 WHERE status != '已退订' 的查询,漏掉了三万个该发邮件的用户:我被 SQL 里 NULL 的三值逻辑坑到背锅的那次群发事故复盘
营销群发,规则是给所有'没退订'的用户发,我写了 WHERE status != '已退订',结果名单比预期少了整整三万人。这三万人有个共同点:status 是 NULL(老系统迁移来、从没设置过)。根因是 SQL 的三值逻辑——NULL 代表'未知',任何与 NULL 的比较(含 !=)结果都是 UNKNOWN,而 WHERE 只保留 …- 4
- 0
-
翻到后面页就超时:MySQL 深分页避坑复盘
有个数据列表接口支持翻页,用的是最朴素的写法 SELECT * FROM orders ORDER BY id LIMIT ?, ?,前端传页码后端算 offset,刚上线数据量小翻哪页都飞快。可随着数据涨到几百万行,用户翻到后面页时接口慢得离谱——翻第一页几毫秒,翻到第一万页要几秒,翻到几十万页直接超时,诡异的是每页明明都只取 20 条数据凭什么翻到后面就这么慢?EXPLAIN 后真相清楚了:很…- 4
- 0
-
从 MySQL 5.7 单实例 + 裸查询 + 全表扫描 + 应用层 N+1 + 无分区 + 无连接池 + 慢查询全靠猜 远古数据层 → 2026 PostgreSQL 17 声明式分区 + 覆盖/部分/GIN 索引 + 逻辑复制读写分离 + PgBouncer + 窗口函数/CTE + JSONB + 物化视图 + pg_stat_statements 现代数据体系 79 天战役复盘:47 套调优修法 + 7 个 P0 复盘 + 6 条工程哲学
17 位数据平台工程师 79 天把一套跑了八年、单库逼近 4.7 亿行的 MySQL 5.7 单实例远古数据层,零中断重构到 2026 年 PostgreSQL 17 现代数据体系:声明式分区裁剪 + 覆盖/部分/GIN/表达式索引 + 逻辑复制读写分离 + PgBouncer 事务级池化 + 窗口函数/CTE 消灭 N+1 + JSONB + 物化视图 + pg_stat_statements …- 3
- 0
-
PostgreSQL 索引设计完全指南:从一次"加索引锁表 4 分钟业务停摆"看懂为什么 CREATE INDEX 远远不够
2023 年我们做一个 SaaS 数据分析平台后端用 PostgreSQL 14 主库一台 32C 128G 加两台只读从库业务初期 100 万订单 1000 万事件一切都很流畅查询都在 50ms 内半年后数据涨到 1 亿订单 8 亿事件我们陆续踩了一堆坑第一种最让我傻眼一个看似普通的 ORDER BY created_at DESC LIMIT 10 查询没建索引前 5 秒加了 b-tree 索…- 5
- 0
-
深分页性能优化完全指南:从一次"翻到第 5000 页、查询慢了 100 倍"看懂 OFFSET 陷阱与游标分页
2021 年我做一个后端服务有一大堆列表页要分页订单列表操作日志消息记录。分页这件事我压根没多想。第一版我做得很省事分页不就是 LIMIT 和 OFFSET 前端要第几页我就 OFFSET 页码减一乘每页条数 LIMIT 每页条数跳过前面那些取这一页该取的。本地开发时真不错测试库里就几百条数据我从第一页翻到最后一页每一页都是瞬间出结果顺畅得很。我心里很踏实分页嘛不就是跳过 N 条取 size 条。…- 3
- 0
-
SQL 索引优化实战:为什么你的查询慢,以及怎么修
"这条 SQL 怎么这么慢?"—— 几乎每个后端工程师都问过这句话。答案十有八九和索引有关:要么没建索引,要么建了用不上,要么建多了拖慢写入。这篇文章不堆理论,而是沿着"索引为什么快 → 为什么用不上 → 怎么诊断 → 怎么建对"这条线走一遍,所有结论都配可复现的 SQL。 索引为什么快:B+ 树的直觉 没有索引时,数据库找一行数据只能做全表扫描:从第一行翻…- 4
- 0
SQL
幸运之星正在降临...
点击领取今天的签到奖励!
恭喜!您今天获得了{{mission.data.mission.credit}}积分
我的优惠劵
-
¥优惠劵使用时效:无法使用使用时效:
之前
使用时效:永久有效优惠劵ID:×
没有优惠劵可用!












