递归查询易因缺失索引或深度过大引发全表扫描、栈溢出或超时;应为id/parent_id建索引、避免非SARGable条件、设MAXRECURSION、防环、压测真实数据。
SQL 递归(比如 WITH RECURSIVE)在没有合适索引支撑时,每次迭代都可能回表查父/子记录,导致实际执行计划里出现多次 Seq Scan 或等价的全表遍历。尤其当树深度大、分支多,而连接字段(如 parent_id)没建索引时,性能会断崖式下降。
实操建议:
id 和 parent_id)都有单独或联合索引WHERE UPPER(name) = 'A'),这会让索引失效EXPLAIN (ANALYZE, BUFFERS) 观察每层迭代是否命中索引不同数据库对递归层级有硬性限制:PostgreSQL 默认 max_recursion_depth = 100(需通过 SET 调整),SQL Server 默认 100 层,超出直接报错 Maximum recursion exceeded;MySQL 8.0+ 虽无硬限制,但深度大时内存增长快,易被 max_execution_time 或 OOM kill。
实操建议:
MAXRECURSION 0(SQL Server)或 SET search_path TO ... 前设好深度上限,防止意外死循环LIMIT 或 WHERE level 主动截断(PostgreSQL / MySQL),别依赖默认值
递归 CTE 默认是 UNION ALL 语义,如果父子关系存在环(如 A→B→C→A),或数据本身有冗余路径(如组织架构中某人同时属两个部门),就会无限生成重复行,最终返回几万甚至百万行——而你只想要 10 个节点。
实操建议:
ARRAY[...] @> ARRAY[id] 检查路径是否已含当前 idJOIN 多张大表,尤其是未加过滤条件的;先收窄 ID 集合,再补关联字段SELECT DIS
TINCT ON (id) 或外层 GROUP BY 去重,但注意这不能替代防环,只是补救