db-indexing(M11)用于审计现有索引是否与实际查询负载匹配,避免缺失、顺序错误或类型错误的索引导致顺序扫描。它服务于性能与规模方向。
检查内容:复合索引列顺序应遵循 Equality → Sort → Range,前导为范围或低选择性列会浪费索引;频繁的 SELECT a,b WHERE c 适合 INCLUDE 覆盖索引,始终带固定谓词(如 WHERE deleted_at IS NULL)的查询适合部分索引;jsonb/array/FTS 包含查询应用 GIN,geometry/range 用 GiST/SP-GiST,自然有序的追加列(时间戳)可用 BRIN,纯 B-tree 或不建索引会被标记;每个外键列都应有覆盖索引,否则在 ON DELETE/ON UPDATE 和连接时会触发顺序扫描,这是产出最高、风险最低的发现。
Tier-0 静态分析解析 DDL/迁移中的索引与外键,对照可见查询模式(ORM where/orderBy、原生 SQL)检测缺失外键索引、复合索引非等值前导列,以及无专用索引的 JSONB/array/FTS/geo 谓词;索引是否真正被使用属于运行时事实,Tier-0 需 API。Tier-1 验证查询可确认未索引外键(Postgres): SELECT conrelid::regclass AS tbl, conname, pg_get_constraintdef(c.oid) AS fk FROM pg_constraint c WHERE c.contype = 'f' AND NOT EXISTS ( SELECT 1 FROM pg_index i WHERE i.indrelid = c.conrelid AND (c.conkey[1]) = i.indkey[0] ); 方法为 index_check,返回的每一行都是已确认的未索引外键。ESR/覆盖问题可用 EXPLAIN (ANALYZE, BUFFERS) 在真实查询上确认扫描类型(explain_plan,Tier-2)。
发现按 schema/finding.schema.json 输出,例如 M11.orders.customer_id_fk_unindexed(severity 3,warn,可自动修复 CREATE INDEX CONCURRENTLY)、M11.events.composite_order_esr(severity 2,warn,建议修复)、M11.posts.jsonb_no_gin(severity 3,warn,建议修复)。每条发现包含逐字引用证据、可复现的目录查询或引用 $DATABASE_URL 的 EXPLAIN,影响以高/中/低区间和置信度标注,不给百分比。
注意:缺失索引并非总是缺陷,小型查找表或写密集表加索引可能更慢,严重度需结合表大小与访问频率,无统计信息时默认 directional。CREATE INDEX CONCURRENTLY 对外键缺口可自动修复(附加、非阻塞、可验证),复合索引重排与部分索引因意图可能不同只做建议。