Files
ccdi/docs/reports/implementation/2026-06-02-fund-graph-timeout-optimization.md

4.2 KiB

资金流图谱接口超时优化实施记录

背景

  • 生产反馈:资金流图谱页面请求 /ccdi/project/fund-graph/graph 出现接口超时。
  • 截图中的请求参数为 keyword=330781199401056317,属于身份证号精确查询场景。
  • 生产数据量约 61 万主体时,原主体定位 SQL 将身份证精确匹配、姓名模糊匹配、object_key 精确匹配混在同一个 OR 条件内,并叠加 ORDER BY CASE,容易导致优化器选择低效执行计划。

修改内容

  1. 拆分主体定位查询:

    • 文件:ccdi-project/src/main/java/com/ruoyi/ccdi/project/mapper/CcdiFundGraphMapper.java
    • 文件:ccdi-project/src/main/resources/mapper/ccdi/project/CcdiFundGraphMapper.xml
    • 新增 selectFundGraphSubjectsByExactKeyword,只查询 idnocfno = keywordobject_key = keyword
    • 新增 selectFundGraphSubjectsByName,仅在精确查询无结果后再执行 name LIKE '%keyword%'
    • selectFundGraphSubjects 保留为 object_key 主键查询,不再执行额外排序。
  2. 调整 Service 调用顺序:

    • 文件:ccdi-project/src/main/java/com/ruoyi/ccdi/project/service/impl/CcdiFundGraphServiceImpl.java
    • /search/graph 的中心节点解析统一走 selectSubjects
    • objectKey 时直接主键查询。
    • objectKey 且有 keyword 时,先精确查询;精确命中后直接返回,不再执行姓名模糊查询。
  3. 优化图谱边查询入口:

    • 文件:ccdi-project/src/main/resources/mapper/ccdi/project/CcdiFundGraphMapper.xml
    • 新增 subjectJoinRowsByCenter,将“中心主体作为起点”和“中心主体作为终点”拆为两段 UNION ALL
    • selectFundGraphEdges 改为引用 subjectJoinRowsByCenter,避免在主体表两侧使用 from_subject.object_key OR to_subject.object_key 作为过滤入口。

影响范围

  • 资金流图谱主体搜索:GET /ccdi/project/fund-graph/search
  • 资金流图谱查询:GET /ccdi/project/fund-graph/graph
  • 边明细查询 GET /ccdi/project/fund-graph/edge-detail 仍使用原明细 SQL 片段,未改变入参和返回结构。
  • 本次未新增数据库字段或索引脚本;现有 DDL 中已包含 lx_fund_flow_subject_node.idnocfnonameobject_key 相关索引。

验证情况

  • 已通过静态断言确认:
    • Mapper 与 XML 已新增精确查询和姓名查询方法。
    • XML 中已移除 OR n.name LIKE 的精确/模糊混用形态。
    • selectFundGraphEdges 已引用 subjectJoinRowsByCenter 且包含 UNION ALL
  • 已通过 XML 格式检查:
    • xmllint --noout ccdi-project/src/main/resources/mapper/ccdi/project/CcdiFundGraphMapper.xml
  • 已通过 MyBatis XML 解析和 SQL 渲染临时检查:
    • selectFundGraphSubjectsByExactKeyword
    • selectFundGraphSubjectsByName
    • selectFundGraphEdges
  • 已通过源码编译:
    • mvn -pl ccdi-project -am -DskipTests compile

验证阻断说明

  • 直接执行 mvn -pl ccdi-project -DskipTests compile 会使用本地仓库中的旧依赖模块,出现既有签名不一致错误;使用 -am 联编依赖模块后通过。
  • 直接执行 mvn -pl ccdi-project -Dtest=CcdiFundGraphTimeoutOptimizationTest test 时,测试编译阶段被既有无关测试源码阻断,未进入本次临时测试断言:
    • CcdiBankStatementTest 仍引用 BankStatementItem#setCustomerCertNosetCustomerSocialCreditCode
    • CcdiFileUploadServiceImplTest 仍按旧的 LsfxAnalysisClient.uploadFile(Integer, Object, String) 签名编写。

生产核对建议

  • 发布后用生产超时样例身份证号重新请求 /ccdi/project/fund-graph/graph,核对接口耗时与返回图谱中心节点。
  • 如生产库是历史库,先确认以下索引存在:
SHOW INDEX FROM lx_fund_flow_subject_node WHERE Key_name IN (
  'PRIMARY',
  'idx_lx_fund_flow_subject_idnocfno',
  'idx_lx_fund_flow_subject_name'
);

SHOW INDEX FROM lx_fund_flow_own_account_edge WHERE Key_name IN (
  'idx_lx_fund_flow_own_from_key',
  'idx_lx_fund_flow_own_to_key'
);

SHOW INDEX FROM lx_fund_flow_detail_edge WHERE Key_name IN (
  'idx_lx_fund_flow_detail_from_date',
  'idx_lx_fund_flow_detail_to_date'
);