SELECT * 是定时炸弹,因使查询对表结构变更敏感且加载冗余大字段;WHERE隐式类型转换会失效索引,需严格匹配字段类型并避免函数包裹索引列。
SELECT * 在生产环境里是定时炸弹它会让查询对表结构变更极度敏感,一旦新增或删减字段,下游应用可能因列数/顺序错位直接报错。更隐蔽的问题是:触发不必要的大字段(如 TEXT、BLOB)加载,拖慢查询、挤占内存、放大锁等待。
实操建议:
select * 模式(如 Django 的 only() / defer(),MyBatis 的 resultMap 显式定义)EXPLAIN 对比加字段前后的执行计划,确认没引入临时表或文件排序WHERE 条件里隐式类型转换正在悄悄拖垮你的索引比如 user_id 是 BIGINT,但写成 WHERE user_id = '123',MySQL 会把所有索引值转为字符串比对,导致全索引扫描。PostgreSQL 更严格,可能直接报错;而 SQL Server 可能按规则强制转列类型,引发意外的隐式转换路径。
实操建议:
setLong() 而非 setString())SHOW WARNINGS(MySQL)或 EXPLAIN (VERBOSE)(PostgreSQL)检查是否出现 type conversion 类提示WHERE DATE(created_at) = '2025-01-01' → 改为 WHERE created_at >= '2025-01-01' AND created_at
典型场景:在事务里调用外部 HTTP 接口、写日志文件、或执行耗时的计算逻辑。这些操作不参与数据库一致性保障,却延长了事务持有锁的时间,导致并发更新阻塞、死锁概率上升、连接池快速耗尽。
实操建议:

BEGIN / COMMIT 块innodb_row_lock_time_avg(MySQL)或 pg_stat_database.blk_write_time(PostgreSQL),数值突增往往意味着事务粒度失控@Transactional(timeout = 3)),防止一个慢查询拖垮整条链路EXPLAIN 验证的 SQL 就是盲写很多 SQL 在测试库跑得飞快,上线后数据量翻十倍就卡死——因为没看执行计划是否走了索引、有没有 Using filesort、是否触发了临时表。更麻烦的是,同一条 SQL 在不同版本 MySQL 或不同统计信息下,执行计划可能完全不同。
实操建议:
EXPLAIN FORMAT=JSON,重点关注 key、rows、Extra 字段JOIN 语句,确认驱动表选择合理(小结果集做驱动),必要时用 STRAIGHT_JOIN 强制pt-query-digest 分析慢日志,找出“平均响应快但 P99 极高”的 SQL——它们往往有隐藏的执行计划抖动真正难的不是写出能返回正确结果的 SQL,而是让它的行为在百万行、高并发、字段变更、统计信息过期等各种现实条件下依然可预期。稳定可控的本质,是把每处隐含假设都变成显式约束。