用途:检测并修复 N+1 查询模式,方法是使用预加载、批量查询或 DataLoader。当查询在循环中运行、ORM 惰性加载导致重复数据库访问时使用。
主要能力:分阶段工作。发现阶段先确认 ORM/框架(ActiveRecord、Django、Prisma、SQLAlchemy、TypeORM、GraphQL)、是否为 GraphQL、能否查看查询日志、是读路径还是写路径。检测阶段通过查询日志识别同一查询结构以不同 ID 重复出现,并关注序列化器/呈现器、回调链、@property 计算属性、条件关联访问、嵌套 N+1、GraphQL 逐字段解析等隐蔽来源。
修复方式:ActiveRecord 区分 preload(单独 WHERE id IN 查询,关联大时安全,不能在同查询中过滤/排序)、eager_load(LEFT OUTER JOIN,需要按关联过滤或排序时用,has_many 可能产生行倍增影响 limit)、includes(自动二选一,隐式切换有风险)。Django 区分 select_related(JOIN,仅 ForeignKey 与 OneToOne)、prefetch_related(独立查询,适用多对多等,可用 Prefetch 带 queryset 过滤)。SQLAlchemy 区分 joinedload(JOIN,集合慎用)、subqueryload(1.4+ 弃用)、selectinload(集合的现代默认)。Prisma 的 include 每层关系发一次查询。DataLoader 用于 GraphQL 及任意循环内逐项异步取数场景,核心是同一事件循环 tick 内批量去重;批处理函数必须按输入键顺序返回结果并对未命中返回 null;每个请求创建一个实例以免跨请求缓存导致数据泄漏。无 ORM 时可手写 IN/ANY 批量查询并在应用层重组,注意 Postgres 参数上限,ID 分批 1000–5000。
适用场景:读端点、GraphQL 解析器、序列化器层、集合关系加载。
限制:预加载并非总是正确修复——大列表中极少访问的关联、多态关联、已分页到单行的详情页可能不值得预加载;排序/过滤需求会决定 JOIN 与子查询选择,可能改变结果顺序或 limit 行为。输出可包括修复代码、查询日志分析、DataLoader 脚手架、检测注释、嵌套 N+1 审计,并说明修复前后预期查询数。