面灵AI→

58 同城 Agent 开发一面:数据分析 Agent 与 Java 基础

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 描述一下这个数据分析 Agent 的主要使用对象、主要功能,以及它解决什么问题。
  2. 这个项目主要解决了什么问题?追问:如果不用 Agent,正常也能取数,那 Agent 带来的价值是什么?
  3. 你提到 MCP 接口,这个 MCP 接口对外包含哪些能力/有多少种方法?
  4. 这个里边有一个你们开发的 Agent 吗?对外跟用户交互的是有一个 Agent 吗?
  5. 外层整个大流程的控制是由项目来控的吗?是 Java 项目吗?相当于在项目里实现了一个工作流?
  6. 整个流程里你们怎么拿到想要的部分?是否是在某个节点请求一次模型?
  7. 以 SQL 生成为例:给很多表和需求,生成 SQL 的整个逻辑是什么?数据来源和流程控制大概分几步?
  8. 第二项生产环境内存问题治理,展开说一下原因、分析过程,以及怎么修复的。
  9. 最后有调 JVM 参数吗?还是只从工程上优化?
  10. 第二个项目都是 Java 相关项目吗?
  11. 校园智能招聘助手里的智能系统涉及 AI 开发吗?
  12. 后面这两个项目都是你在学校做的课题或实验室项目吗?
  13. 你熟悉的语言主要就是以 Java 为主吗?
  14. 你有真正自己开发过 Agent 或写过 Skill 吗?不一定生产,自己练习也行。
  15. 说一下 Spring 的动态代理。
  16. MySQL 熟悉是吧?说一下 MySQL 的索引。
  17. 现场写一个你比较熟悉的排序算法,伪代码或完整代码都可以。

《参考解析》

数据分析 Agent 的价值不是「替人写 SQL」,而是把取数链路缩短。 使用对象通常是运营、产品、业务分析这类懂问题但未必熟 SQL 的人,功能包括自然语言问数、指标解释、维度下钻、异常归因和图表生成。传统 BI 也能取数,但需要人先知道表结构、口径和 JOIN 关系,再写 SQL、等结果、反复改;Agent 把「理解意图 → 找表 → 生成 SQL → 校验 → 执行 → 解释结果」串起来,能多轮追问,也能在失败时自动修正。它的代价是延迟、成本和不确定性,所以适合探索式、口径相对稳定的分析,不适合强一致、强审计的核心报表——后者仍然要走固化模型和人工复核。

MCP 接口要按「能力」而不是「方法数量」回答。 一个数据分析 MCP 通常暴露几类能力:列出数据源/表、描述表结构与字段含义、检索指标口径、执行只读 SQL、返回结果与执行计划、可能还有画图或导出。方法数不是重点,重点是把 schema、权限、超时、行数限制和错误码定义清楚,让 Agent 知道什么时候该调用哪个。外层如果已经有 Java 服务,Agent 可以作为其中一个节点:Java 控流程、鉴权、审计和结果落库,模型只在「选表、生成 SQL、解释异常」这些需要判断的节点被调用,而不是让模型接管整个请求生命周期。

SQL 生成是一条带校验的流水线。 第一步解析问题,识别指标、维度、时间范围、过滤条件和期望粒度;第二步做 schema linking,从大量表里召回相关表与字段,连同字段注释、枚举值、示例值一起放进上下文;第三步生成 SQL,要求只读、带 limit、使用指定方言;第四步静态校验(语法、表字段是否存在、是否全表扫描、是否命中分区)和权限校验;第五步执行,失败时把数据库错误和结果空/异常回传给模型做一次修复;最后把 SQL、口径、结果和假设一起返回给用户。数据来源要标新鲜度和口径版本,避免模型把相似字段拼错。整个链路要有 trace,能回放是哪一步出错。

生产内存问题治理先取证,再改代码或参数。 先看监控曲线是缓慢上涨还是阶梯上涨,配合 GC 日志判断是老年代泄漏、频繁 Full GC,还是堆外/元空间/线程栈问题;然后抓 heap dump,用 MAT 或 JProfiler 看 dominator tree,找占比最大的对象和 GC root 引用链,常见嫌疑是无界缓存、静态集合、ThreadLocal 未清理、连接/流未关闭、类加载器泄漏、直接内存。修复优先改代码:给缓存设上限和过期、拆分大对象、及时 close、避免一次性把大结果集读进内存;参数是辅助手段,比如按容器 limit 设置 -Xmx、合理的 -XX:MaxDirectMemorySize、选低停顿 GC、开 HeapDumpOnOutOfMemoryError。改完要在压测里复现并观察 Full GC 次数、老年代回收后占用和 RSS,确认不是把问题推迟。

Spring 动态代理分 JDK 和 CGLIB 两条路。 JDK 代理要求目标类实现接口,运行时生成实现同一接口的代理类,方法调用转发到 InvocationHandler;CGLIB 通过继承生成子类,覆盖非 final 方法,不需要接口,但 final 类和 final 方法代理不了。Spring AOP 原生默认有接口用 JDK、没有接口用 CGLIB,也可以通过 proxyTargetClass=true 强制 CGLIB;Spring Boot 2.x 起自动配置默认走 CGLIB。代理对象是 AOP 生效的边界:同类内部方法自调用不走代理,事务/缓存/切面会失效,这是常见坑。

MySQL 索引的主线是 B+ 树、聚簇与最左前缀。 InnoDB 主键索引是聚簇索引,叶子节点存整行;二级索引叶子存主键值,查非覆盖字段要回表。联合索引按定义顺序排序,遵循最左前缀,范围查询之后的列通常用不上索引;能用覆盖索引就避免回表。设计时看选择性、区分度、查询模式,别给低基数列盲目加索引;用 EXPLAIN 看 type、key、rows、Extra,关注全表扫描、filesort、临时表和回表次数。索引不是越多越好,写入放大、空间和优化器选择成本都要算。

手写排序优先写快排,但要讲清边界。 选基准、分区、递归左右;工程上随机选基准或三数取中,避免有序数组退化到 O(n²),小数组切换插入排序,递归深度过大时改用堆排。若要求稳定排序就写归并,时间 O(n log n)、额外 O(n) 空间。面试时先把思路和复杂度说清,再写代码,最后补一句「Java 里直接用 Arrays.sort,对象数组是 TimSort,基本类型是双轴快排」。