Agent应用与普通Web应用有一个明显区别:它会频繁写入会话消息、工具调用结果、任务执行日志等数据,查询模式也往往以“按会话ID拉取历史消息”“按任务状态筛选”为主。一旦数据量增长到百万级,缺乏优化的数据库会成为整个Agent系统的瓶颈,表现为响应延迟飙升、模型调用排队、甚至超时失败。本文围绕索引设计与慢查询排查两大主题,给出一套可落地的优化思路。

Agent场景下数据库为什么容易变慢
先看一个典型的表结构。很多团队会把Agent的对话历史直接存在一张messages表里,包含session_id、role、content、created_at等字段。写入时看似没问题,但当单表数据达到千万级,按session_id查询历史消息的耗时会从几毫秒恶化到几秒。
CREATE TABLE messages ( id BIGINT AUTO_INCREMENT PRIMARY KEY, session_id VARCHAR(64), role VARCHAR(16), content TEXT, created_at DATETIME, KEY idx_session (session_id) ) ENGINE=InnoDB;
问题往往不在表结构本身,而在访问模式。Agent的一个特点是上下文回溯频繁:用户每发一条消息,系统都要拉取该会话最近的N条记录拼进提示词。如果索引只建了session_id单列,查询虽然能命中,但回表取content大字段的开销巨大,再加上会话消息按时间倒序排列需要额外排序,性能自然上不去。
另一个常见原因是写入放大。Agent执行一次任务可能产生几十条工具调用日志,如果这些日志表没有合理归档策略,写入热点集中、页分裂频繁,还会拖累同一实例上的读查询。理解了这些场景,才能对症下药,而不是盲目加机器。
索引设计的核心原则与实战技巧
索引设计的首要原则是贴合查询路径。对于“按会话查最近消息”这类高频查询,复合索引的效果远好于单列索引。以(session_id, created_at)建复合索引,查询时可以直接按索引顺序扫描,避免filesort:
-- 复合索引消除排序 ALTER TABLE messages ADD INDEX idx_session_time (session_id, created_at); SELECT content, role FROM messages WHERE session_id = 'abc123' ORDER BY created_at DESC LIMIT 20;
复合索引遵循最左前缀原则,字段顺序非常关键。一般把等值条件字段放前面,范围或排序字段放后面。如果查询还带了status等过滤条件,可以考虑(session_id, status, created_at)这样的顺序。设计前先梳理清楚系统的所有核心查询,列出WHERE、ORDER BY、GROUP BY中出现的字段,再决定索引组合,避免建一堆用不上的索引白白消耗写入性能。
覆盖索引是进阶技巧。如果查询的字段全部包含在索引里,数据库无需回表,速度会有数量级提升。比如统计某会话消息数量,建(session_id, role)索引后,count查询纯走索引,几乎瞬间完成。但要注意content这种TEXT大字段不适合直接放进索引,更合理的做法是把大字段拆到单独的表,主表只保留摘要或内容长度等元信息,需要时再按主键取详情。
同时要警惕索引失效的典型场景:对索引列使用函数或运算、隐式类型转换(session_id是VARCHAR却用数字查询)、前导模糊匹配LIKE '%xxx'、OR连接的非索引列等。遇到查询不命中索引时,优先检查这些坑。
慢查询排查流程与执行计划分析
排查慢查询的第一步是开启慢查询日志,把long_query_time设为0.5秒或1秒,收集真实业务中的问题SQL:
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 0.5; SET GLOBAL log_queries_not_using_indexes = ON;
拿到慢SQL后,用EXPLAIN分析执行计划,重点关注几个字段:type列如果是ALL说明全表扫描,至少要优化到range或ref级别;rows列表示预估扫描行数,数值越大越危险;Extra列出现Using filesort或Using temporary通常意味着排序或分组没有走索引。例如下面这个执行计划就暴露了明显问题:
EXPLAIN SELECT * FROM messages WHERE session_id = 'abc123' AND role = 'tool' ORDER BY created_at DESC; -- 若type为ALL且Extra含Using filesort -- 说明缺少 (session_id, role, created_at) 复合索引
除了加索引,还有一些针对Agent场景的专项优化。深分页是重灾区,LIMIT 100000, 20这种写法会扫描前十万行再丢弃,改用游标分页(记录上一页最后一条的created_at和id作为查询条件)可以将耗时稳定在毫秒级。历史消息表要尽早规划归档,比如超过90天的数据迁移到冷存储,主表保持精瘦。读写分离和连接池配置也值得检查,Agent并发调用时如果连接池太小,请求会在应用层排队,看起来像数据库慢,实际是资源分配问题。
最后强调一点:优化是一个循环过程。上线新索引后要持续观察慢查询日志和监控指标,验证效果,同时留意索引对写入性能的影响。把索引设计、SQL审查、归档策略这套组合拳打好,Agent系统的数据库才能在数据量持续增长时依然保持稳定的响应速度。
Agent数据库优化索引设计慢查询修改时间:2026-09-04 20:45:34