应优先分析子查询的执行耗时而非行数PostgreSQL看Subquery Scan的Actual Total TimeMySQL用EXPLAIN FORMATJSON查SUBQUERY/DERIVED的rows与filtered若rows大且filtered低则索引失效。怎么看 EXPLAIN 里哪个子查询最拖后腿嵌套查询慢不是“整个查询慢”而是某个子查询在执行计划里占了 70% 的开销。关键不是看 EXPLAIN 输出的行数而是看每一步的 costPostgreSQL或 rows × Extra 中的 Using temporary/Using filesortMySQL。PostgreSQL重点关注 Plan Rows 和 Actual Total Time如果某层 Subquery Scan 的 Actual Total Time 明显高于父节点它就是瓶颈MySQL用 EXPLAIN FORMATJSON搜 select_type: SUBQUERY 或 DERIVED看里面的 rows 和 filtered —— 若 rows 过大比如 50 万且 filtered 低于 10%说明没走好索引子查询结果集膨胀了别只盯着第一行嵌套越深执行计划缩进越靠右但最右边那行未必最重要顺着 id 或 select_id 把每个子查询分支单独拎出来比耗时为什么 IN (SELECT ...) 比 JOIN 慢这么多这不是语法风格问题是优化器对两种结构的处理逻辑根本不同IN 子查询在 MySQL 5.6 前默认不重写为半连接容易触发重复执行而 JOIN 能利用驱动表 被驱动表的索引下推。MySQL当外层条件带 WHERE 时IN (SELECT ...) 可能被当作“依赖子查询”select_type DEPENDENT SUBQUERY导致对主表每行都执行一次子查询PostgreSQLIN 会转成 Hash Semi Join但如果子查询返回 NULL语义上要额外过滤可能退化为 Nested Loop实操建议把 IN (SELECT id FROM t2 WHERE ...) 改成 EXISTS (SELECT 1 FROM t2 WHERE t2.id t1.id AND ...)或者直接 JOIN 后 DISTINCT —— 不为可读性只为让优化器选更稳的连接路径EXPLAIN ANALYZE 显示 Buffers: shared hitxxx 但还是慢缓存命中高只说明没刷磁盘不代表计算不重。尤其嵌套查询中大量 shared hit 可能来自反复扫描同一张中间结果表比如 CTE 或派生表CPU 和内存带宽早被打满了。 标贝科技 标贝科技-专业AI语音服务的人工智能开放平台