用途:检查查询写法是否让索引失效,覆盖 ORM 源码与原生 SQL,服务于性能与规模评分(关系型 Query 权重 18,与 M3/M19 共享)。
主要能力:
- SELECT *:抓取全部列会破坏覆盖索引、增大网络与缓存开销,并让代码耦合列顺序;在热路径中标记。
- 结构性 N+1:循环内查询或逐行懒加载关系,本应合并为一次 join 或批量 IN。静态检测是方向性的(循环运行时基数未知),只指出结构,不声称行数。
- OFFSET 分页:LIMIT n OFFSET m 随深度线性劣化;深分页应改用 keyset/seek,如 WHERE id > $last ORDER BY id LIMIT n。
- 非 SARGable 谓词:把索引列包进函数(WHERE lower(email)=…、WHERE date(created_at)=…、前导通配符 LIKE '%x'、隐式类型转换)导致索引不可用;建议表达式索引或重写谓词。前导通配符 LIKE '%x%' 场景 B-tree 永远无效,应指出补救:在列上建 pg_trgm GIN/GiST 索引,或对重度全文检索使用专用搜索引擎。
使用方式:Tier-0 静态阶段用 grep 检查 ORM 调用点与原生 SQL 中的 SELECT *、函数包裹索引列、前导通配符 LIKE、OFFSET,并检测循环/.map/逐项关系访问中的查询调用以发现 N+1。所有查询模式发现从源码看至多是方向性的;确认实际计划/成本需运行时(needs_api / Tier-2)。Tier-1/2 验证查询:EXPLAIN (ANALYZE, BUFFERS) <可疑查询>;方法 explain_plan。索引存在却出现 Seq Scan 可确认非 SARGable 谓词;实际 rows × loops 可确认 N+1 放大。Tier-2 的 pg_stat_statements(按 total_exec_time 排序)可暴露真实热点查询;没有它,热点判断是方向性的。
发现项按 schema/finding.schema.json 输出,例如 M13.orders.select_star_hot_path(severity:2,warn,axis performance,confidence directional,fixable: proposed)、M13.users.n_plus_one_posts(severity:3,warn,directional,fixable: advisory,需应用侧预加载/批处理)、M13.feed.offset_deep_pagination(severity:2,warn,directional,fixable: proposed,keyset 重写)、M13.users.non_sargable_lower_email(severity:3,warn,directional,fixable: proposed,表达式索引或谓词重写)。每条发现:evidence.observed 逐字引用查询/调用点(密钥脱敏);verification.reproduce 为上述 EXPLAIN 并引用 $DATABASE_URL,或对该模式的 grep;expected_impact 带区间与置信度标签,不给出裸百分比。
限制与诚实说明:N+1 按设计是方向性的——循环跑两次无妨,同样循环跑 1 万行则不然,静态分析无法区分,因此不设上限、不引用倍数。SELECT * 在小查找或一次性管理查询中无害,严重度应限定在热路径。改变结果语义的重写(keyset、谓词重构)只作提议/建议,绝不自动执行;新增表达式索引可提议。