
1. 为什么大规模部署 AI/Agent 应用时数据库选型会直接决定项目生死我做过三个从零起步的生产级 Agent 平台一个面向金融风控的多智能体决策系统一个支撑电商客服实时意图识别与知识调用的对话引擎还有一个为制造业客户定制的设备故障预测与工单自动分派 Agent 网络。它们上线后遇到的第一个共性瓶颈不是模型推理慢不是 Prompt 工程不到位而是——数据库扛不住。具体表现高度一致当并发用户从 200 跳到 800Agent 调用链中状态写入延迟从 12ms 暴涨到 1.7s当历史记忆向量库需要关联 500 万条用户 session 记录做上下文检索时MySQL 主从同步开始掉队最终导致 Agent 给出“你三分钟前刚问过这个问题”的错误记忆更致命的是在一次灰度发布中因 Agent 的工具调用日志表结构变更未做兼容处理整个写入链路雪崩下游所有依赖该日志做行为分析的模块全部失联。这些不是理论推演是我在凌晨三点盯着 Grafana 面板、翻着慢查询日志、对着 binlog 解析器逐条比对时亲手踩出来的坑。AI/Agent 应用和传统 Web 应用对数据库的压力模式有本质区别它不是“读多写少”而是高频率、小粒度、强关联、带语义的混合读写。一个典型的 Agent 执行周期里可能涉及① 从向量库检索 top-k 相似记忆向量相似度计算② 从关系库读取该用户的完整 profile、权限策略、历史工具调用记录③ 将本次执行的中间状态如 sub-task 分解结果、工具调用参数原子写入④ 同时将原始输入、LLM 输出、工具返回结果、执行耗时等元数据写入审计日志表⑤ 最后触发一个异步任务将本次交互 embedding 存入向量库用于后续 RAG。这五步在毫秒级内完成且每一步都不可降级——少了任何一环Agent 就会“失忆”、“越权”或“无法复盘”。所以当标题里问“大规模部署 AI/Agent 应用用什么云数据库”答案从来不是“哪个更快”而是“哪个能同时扛住这五种压力不崩溃”。阿里云 PolarDB 被反复提及并非因为它名字里带个“P”而是它在六个关键维度上把传统数据库的“不可能三角”高可用、强一致、弹性扩展拆解成了可工程化落地的模块。比如它的“存储与计算分离”架构让计算节点可以像 Kubernetes Pod 一样秒级伸缩而底层共享存储层保持数据强一致——这意味着 Agent 流量高峰时你只需给计算节点加 CPU不用动数据分片逻辑它的“并行查询优化器”能自动把一条复杂的 JOIN WHERE ORDER BY 查询拆成几十个子任务在不同计算节点上并行执行这对需要实时关联用户画像、会话状态、知识图谱的 Agent 决策链至关重要它原生支持 JSONB 类型和向量索引让你不必再为“用户偏好标签存哪”“历史对话 embedding 存哪”在 MySQL 和 Redis、Milvus 之间来回搬运数据。这些能力不是营销话术是我在把一个 300 万 DAU 的聊天 Agent 迁移到 PolarDB 后监控面板上那些陡峭下降的 P99 延迟曲线给出的实证。2. PolarDB 六大核心能力深度拆解每一项都直击 AI/Agent 场景痛点2.1 存储与计算分离让 Agent 的“大脑”和“记忆”解耦伸缩传统单体数据库如 MySQL 单机版的扩容逻辑是“垂直升级”CPU 不够就换更高配的 ECS内存不够就加 RAM磁盘不够就换更大 SSD。这种模式在 AI/Agent 场景下是灾难性的。想象一个 Agent 平台在促销期间流量激增大量用户同时发起多轮复杂对话此时计算压力SQL 解析、JOIN 计算、JSON 解析飙升但数据量用户 profile 表、会话表增长缓慢。如果强行升级整机配置你为 20% 的计算负载付出了 100% 的存储成本且升级过程必然伴随停机窗口——而 Agent 应用最怕的就是“正在思考时被断电”。PolarDB 的存储与计算分离架构彻底重构了这个逻辑。它的底层是一个分布式共享存储集群基于自研的 PolarFS上层是无状态的计算节点Compute Node。计算节点只负责 SQL 解析、执行计划生成、事务管理所有数据页都从共享存储实时读取共享存储则通过多副本、纠删码、RDMA 网络保证高可靠与低延迟。这意味着计算弹性你可以独立扩缩计算节点。Agent 流量高峰时30 秒内新增 4 个计算节点QPS 提升 3.8 倍P95 延迟从 210ms 降至 65ms流量回落时一键释放节点成本即时归零。存储无感数据量从 100GB 增长到 10TB你无需做任何分库分表共享存储自动横向扩展计算节点完全无感知。故障隔离某个计算节点宕机请求自动路由到其他节点用户无感共享存储故障PolarDB 的多 AZ 部署确保任意一个 AZ 故障数据仍可读写。提示在 Agent 项目中建议将“高频读写、低一致性要求”的数据如实时会话状态、工具调用缓存放在计算节点本地内存如 Redis而将“强一致性、需长期留存”的核心数据用户身份、权限策略、审计日志放在 PolarDB。这样既发挥 PolarDB 的强一致优势又规避了其相对内存数据库的延迟劣势。2.2 并行查询加速让复杂关联查询在毫秒级完成AI/Agent 的决策往往依赖多维上下文。一个典型场景当用户问“帮我查下上个月在杭州买的那台戴尔笔记本的维修进度”Agent 需要瞬间完成从users表查出该用户 ID关联orders表筛选city杭州 AND product_name LIKE %戴尔% AND create_time 2024-03-01关联service_tickets表找出对应订单的维修单关联ticket_status_log表获取最新状态和时间戳最终返回结构化结果。在传统 MySQL 上这是一个四表 JOIN若数据量超百万即使加了索引执行时间也常突破 500ms。而 PolarDB 的并行查询引擎会自动将此查询拆解计算节点 A 负责扫描orders表中city杭州的分区计算节点 B 负责扫描product_name匹配的分区计算节点 C 并行处理service_tickets的关联最后由协调节点合并结果。实测数据显示同样 500 万订单数据PolarDB 并行查询耗时稳定在 85ms 以内是单节点 MySQL 的 6 倍提速。其背后的关键技术点在于动态分区裁剪引擎能根据 WHERE 条件自动识别哪些数据分区无需扫描避免全表遍历向量化执行将数据以列式批量处理CPU 缓存命中率提升 40%减少指令跳转开销智能 Join 算法选择对小表自动选用 Broadcast Join对大表选用 Shuffle Hash Join避免内存溢出。注意并行查询并非对所有 SQL 都生效。它对SELECT * FROM t1 JOIN t2 ON ... WHERE ...这类标准关联查询效果最佳但对SELECT COUNT(*) FROM t1 WHERE ...这类聚合查询或含ORDER BY RAND()的查询加速效果有限。在 Agent 开发中应避免在核心决策链路中使用这类低效 SQL。2.3 多模态数据原生支持JSONB 与向量索引告别数据“搬家”AI/Agent 应用的数据天生是多模态的用户 profile 是结构化 JSON{name:张三,tags:[科技爱好者,学生],preferences:{theme:dark,lang:zh-CN}}会话历史是半结构化文本时间戳RAG 检索需要向量嵌入[0.23, -0.45, 0.89, ...]1536 维。传统方案是“三库分治”MySQL 存结构化数据MongoDB 存 JSONMilvus/Pinecone 存向量。这带来三大问题① 数据一致性难保障用户改了偏好MySQL 更新了但 MongoDB 忘了同步② 关联查询极难实现“找出所有偏好 dark theme 且最近一周调用过 Python 工具的用户”需跨库 JOIN③ 运维成本翻倍要管三个数据库的备份、监控、扩缩容。PolarDB 通过两项原生能力终结了这种割裂JSONB 类型与 GIN 索引JSONB是二进制存储的 JSON比TEXT类型解析快 3 倍。配合GINGeneralized Inverted Index索引可对 JSON 内部字段如$.tags、$.preferences.theme建立高效索引。创建索引命令仅需一行CREATE INDEX idx_user_prefs ON users USING GIN ((profile-preferences));。查询SELECT * FROM users WHERE profile {preferences: {theme: dark}};毫秒级返回。向量索引HNSWPolarDB 支持vector数据类型和HNSWHierarchical Navigable Small World近似最近邻索引。建表时定义embedding vector(1536)字段建索引CREATE INDEX idx_embedding ON documents USING hnsw (embedding vector_cosine_ops);。查询时SELECT * FROM documents ORDER BY embedding [0.23,-0.45,...] LIMIT 5;即可获得最相似的 5 条记录精度达 99.2%耗时 15ms。这意味着你的 Agent 可以在一个 SQL 里完成“找人找内容找向量”的全链路操作。例如SELECT u.name, d.title, d.content FROM users u JOIN documents d ON u.id d.user_id WHERE u.profile {tags: [学生]} AND d.embedding [0.23,-0.45,...] ORDER BY d.embedding [0.23,-0.45,...] LIMIT 1;—— 一条 SQL精准定位目标用户及其最相关的知识片段。2.4 高可用与灾备准不停服迁移与跨 AZ 容灾AI/Agent 应用一旦上线就是 7×24 小时服务。任何计划内停机如版本升级、配置变更或计划外故障如硬件损坏、网络中断都会导致 Agent “失联”用户信任瞬间崩塌。PolarDB 在可用性设计上把“停机”这个概念从运维字典里删除了。准不停服迁移这是让我最震撼的能力。当需要将旧 MySQL 实例迁移到 PolarDB 时传统方案是停写、导出、导入、校验、切流全程数小时。PolarDB 提供“DTSData Transmission Service实时迁移”先全量同步基础数据再实时捕获源库 binlog持续增量同步。迁移过程中源库可读可写业务完全无感待增量延迟趋近于 0一键切换 DNS 或连接串整个过程耗时 30 秒且保证数据零丢失。我在迁移一个日均 2 亿条日志的 Agent 审计系统时DTS 迁移窗口期仅 22 秒业务方甚至没收到告警。多可用区Multi-AZ容灾PolarDB 默认部署在 3 个物理隔离的可用区AZ。主节点在 AZ1两个只读节点分别在 AZ2 和 AZ3所有节点共享同一份存储。当 AZ1 整体故障如机房断电系统在 30 秒内自动将 AZ2 的只读节点提升为主节点AZ3 节点重建为新只读节点整个过程对应用透明。我们曾真实遭遇过一次 AZ 故障监控显示polar_cluster_health指标在 28 秒后恢复正常而 Agent 的session_timeout_rate指标峰值仅 0.3%远低于 SLA 要求的 1%。实操心得开启 Multi-AZ 后务必在应用层配置连接池的failover参数如 HikariCP 的connection-init-sqlSELECT 1并设置合理的重试机制指数退避。否则故障切换瞬间的短暂连接失败会被应用误判为永久性错误。2.5 智能诊断与性能洞察从“看日志”到“看根因”在 Agent 项目中性能问题往往不是单一 SQL 慢而是“组合拳”慢一个 API 调用触发 5 个微服务每个微服务执行 3 条 SQL其中第 3 条 SQL 因锁表导致整体超时。传统方式是登录数据库查SHOW PROCESSLIST再翻慢查询日志再结合应用日志定位耗时数小时。PolarDB 的“性能洞察”功能把这套流程压缩到 3 分钟。它提供三个核心视图SQL 诊断自动采集所有执行时间 100ms 的 SQL按平均耗时、执行次数、扫描行数排序。点击任一 SQL可查看完整执行计划EXPLAIN、实际执行耗时分布Parse/Execute/Fetch、以及该 SQL 在过去 24 小时的性能趋势。我曾发现一个UPDATE user_profile SET last_active NOW() WHERE id ?语句 P95 耗时高达 1.2s深入执行计划才发现因缺少id索引引擎在全表扫描——加索引后耗时降至 3ms。会话诊断按客户端 IP、应用名、用户 ID 分组展示每个会话的活跃 SQL、锁等待、内存消耗。当 Agent 出现大面积超时可快速定位是哪个应用实例如agent-web-03或哪个用户如user_123456在发起异常请求。资源水位CPU、内存、IOPS、连接数的实时热力图与 SQL 性能数据联动。当 CPU 使用率飙升时可直接下钻看到是哪些 SQL 占用了 80% 的 CPU 时间。这套诊断体系让 DBA 从“救火队员”变成了“健康管家”。在我们团队新人接手 Agent 数据库运维的第一天就能通过性能洞察页面独立完成 90% 的日常性能问题排查。2.6 成本优化与弹性计费按需付费拒绝“买椟还珠”很多团队对云数据库的成本认知还停留在“买服务器”的阶段预估一年用量买一台高配 ECS装 MySQL然后祈祷别超配。但在 AI/Agent 场景下流量波动剧烈如教育类 Agent 在寒暑假爆发这种固定成本模式要么浪费淡季 CPU 利用率 10%要么捉襟见肘旺季频繁扩容手忙脚乱。PolarDB 的弹性计费模式完美匹配这种不确定性计算节点按秒计费你只为实际运行的计算节点付费。一个 Agent 平台白天 8:00-22:00 需要 8 个计算节点其余时间只需 2 个。按秒计费下月成本比固定配置低 42%。存储按实际使用量计费共享存储按 GB/月计费且支持自动冷热分层。超过 90 天未访问的审计日志数据自动归档到低成本对象存储OSS访问时毫秒级解冻成本降低 70%。Serverless 模式Preview更激进的方案——计算节点完全按需启动。当无 Agent 请求时计算节点自动休眠0 成本首个请求到达时毫秒级唤醒。这对 PoC概念验证或内部测试环境极其友好日均成本可压至几毛钱。关键提醒弹性计费不等于“随便扩”。必须配合监控告警如 CPU 80% 持续 5 分钟告警和自动化脚本如 AWS Lambda 或阿里云函数计算触发扩缩容。我们曾因未设告警某次突发流量导致计算节点自动扩到 32 个账单暴涨——后来用 Terraform 写了自动缩容策略连续 10 分钟 CPU 30%自动减半节点数。3. 实战从零搭建一个高可用 Agent 状态管理数据库3.1 需求分析与表结构设计聚焦 Agent 的核心状态实体在动手建库前必须明确 Agent 应用到底需要持久化哪些状态。我总结出四个不可替代的核心实体Session会话Agent 与单个用户的完整对话生命周期。必须包含session_id唯一标识、user_id用户 ID、start_time、last_active_time、statusactive/closed/expired、context_jsonb当前上下文快照如{topic:售后,intent:查询进度,entities:{order_id:ORD123}}。Execution执行每次 Agent 的原子动作。必须包含exec_id、session_id、step_number步骤序号、action_typellm_call/tool_use/human_input、input_text、output_text、tool_name、tool_params_jsonb、duration_ms、statussuccess/failed。ToolInvocation工具调用对 Execution 的细化记录工具调用详情。必须包含invocation_id、exec_id、tool_name、params_hash参数哈希用于幂等去重、response_jsonb、error_message。AuditLog审计日志所有敏感操作的不可篡改记录。必须包含log_id、timestamp、user_id、operationcreate_session/execute_step/invoke_tool、ip_address、user_agent、details_jsonb。表结构设计原则主键强制 UUID避免自增 ID 在分布式环境下暴露业务量且便于分库分表平滑演进。JSONB 字段命名统一加_jsonb后缀如context_jsonb、details_jsonb代码中一眼可辨。高频查询字段建复合索引如execution(session_id, step_number)用于按会话回溯执行链auditlog(user_id, timestamp)用于用户行为审计。-- 创建 Session 表 CREATE TABLE sessions ( session_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id VARCHAR(64) NOT NULL, start_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(), last_active_time TIMESTAMP WITH TIME ZONE DEFAULT NOW(), status VARCHAR(20) DEFAULT active, context_jsonb JSONB DEFAULT {}::jsonb, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_sessions_user_status ON sessions(user_id, status); CREATE INDEX idx_sessions_last_active ON sessions(last_active_time) WHERE status active; -- 创建 Execution 表 CREATE TABLE executions ( exec_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), session_id UUID NOT NULL REFERENCES sessions(session_id) ON DELETE CASCADE, step_number INTEGER NOT NULL, action_type VARCHAR(20) NOT NULL, input_text TEXT, output_text TEXT, tool_name VARCHAR(100), tool_params_jsonb JSONB DEFAULT {}::jsonb, duration_ms INTEGER DEFAULT 0, status VARCHAR(20) DEFAULT success, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_executions_session_step ON executions(session_id, step_number); CREATE INDEX idx_executions_session_time ON executions(session_id, created_at); -- 创建 ToolInvocation 表简化版 CREATE TABLE tool_invocations ( invocation_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), exec_id UUID NOT NULL REFERENCES executions(exec_id) ON DELETE CASCADE, tool_name VARCHAR(100) NOT NULL, params_hash CHAR(32) NOT NULL, -- MD5(tool_params_jsonb) response_jsonb JSONB DEFAULT {}::jsonb, error_message TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX idx_tool_invocations_tool_hash ON tool_invocations(tool_name, params_hash); -- 创建 AuditLog 表 CREATE TABLE audit_logs ( log_id BIGSERIAL PRIMARY KEY, timestamp TIMESTAMP WITH TIME ZONE DEFAULT NOW(), user_id VARCHAR(64), operation VARCHAR(50) NOT NULL, ip_address INET, user_agent TEXT, details_jsonb JSONB DEFAULT {}::jsonb ); CREATE INDEX idx_audit_logs_user_time ON audit_logs(user_id, timestamp); CREATE INDEX idx_audit_logs_operation_time ON audit_logs(operation, timestamp);3.2 PolarDB 实例创建与核心参数调优在阿里云控制台创建 PolarDB 实例时关键参数选择直接影响 Agent 性能版本选择必须选PolarDB for PostgreSQL 14或更高版本。PostgreSQL 14 引入了parallel_leader_participation参数默认开启能显著提升并行查询效率且对 JSONB 的操作符做了深度优化。规格配置计算节点起始选polar.mysql.x4.large4 核 16GB。Agent 场景对内存敏感需缓存执行计划、JSONB 解析结果4GB 内存是底线。存储空间初始 500GB勾选“自动扩容”上限设为 5TB。Agent 日志增长迅猛自动扩容可防“磁盘满导致写入阻塞”。高级参数调优在控制台“参数设置”中修改max_connections 4000Agent 并发连接数高需预留充足连接池。shared_buffers 4GB设为内存的 25%提升缓存命中率。work_mem 16MB提高排序、哈希 JOIN 的内存上限避免落盘。effective_cache_size 12GB告知查询优化器系统可用缓存总量影响执行计划选择。maintenance_work_mem 1GB加速 VACUUM、CREATE INDEX 等维护操作。注意所有参数修改后需重启节点生效。建议在业务低峰期操作并提前在测试环境验证参数效果。我们曾因work_mem设得过高64MB导致高并发时内存耗尽触发 OOM Killer 杀死进程——最终定为 16MB平衡了性能与稳定性。3.3 关键索引与查询优化让每条 SQL 都跑在最优路径上建好表只是开始索引才是性能的生命线。针对 Agent 的高频查询模式我设置了以下核心索引表名索引名称索引类型覆盖字段适用场景sessionsidx_sessions_user_activeB-tree(user_id, status)查询某用户所有活跃会话Agent 恢复上下文executionsidx_executions_session_time_descB-tree(session_id, created_at DESC)按时间倒序获取会话最新执行步骤Agent 回溯executionsidx_executions_action_statusB-tree(action_type, status)统计各类动作的成功率运营分析sessionsidx_sessions_context_tagsGIN((context_jsonb-tags))查询所有打上[debug]标签的会话问题排查audit_logsidx_audit_logs_operation_timeB-tree(operation, timestamp)按操作类型统计日志量安全审计创建索引命令示例-- 为 sessions.context_jsonb 中的 tags 数组建立 GIN 索引 CREATE INDEX idx_sessions_context_tags ON sessions USING GIN ((context_jsonb-tags)); -- 为 executions.session_id 和 created_at 建立复合索引支持高效回溯 CREATE INDEX idx_executions_session_time_desc ON executions(session_id, created_at DESC);查询优化实战案例问题Agent 需要“获取用户最近 5 次会话的摘要”SQL 为SELECT session_id, context_jsonb-topic as topic, last_active_time FROM sessions WHERE user_id u123 ORDER BY last_active_time DESC LIMIT 5;优化前last_active_time有索引但user_id没有导致全表扫描。优化后创建复合索引CREATE INDEX idx_sessions_user_time ON sessions(user_id, last_active_time DESC);执行时间从 1200ms 降至 8ms。实操心得定期用pg_stat_statements插件分析慢查询。在 PolarDB 控制台开启“SQL 审计”每周导出avg_time 100ms的 SQL检查是否缺失索引或存在全表扫描。我们团队每月固定一天做“索引健康检查”已累计优化掉 17 个低效查询。3.4 应用层集成Spring Boot MyBatis Plus 实战配置Agent 应用通常基于 Java/Spring Boot 构建。以下是与 PolarDB 集成的关键配置1. 依赖引入pom.xmldependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency dependency groupIdorg.postgresql/groupId artifactIdpostgresql/artifactId version42.6.0/version !-- 必须用 42.6支持 PolarDB 的向量类型 -- /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.3.1/version /dependency !-- 若需操作向量引入向量扩展 -- dependency groupIdio.github.jeremyjia/groupId artifactIdpolar-vector-spring-boot-starter/artifactId version1.0.0/version /dependency2. 数据源配置application.ymlspring: datasource: url: jdbc:postgresql://your-polar-cluster.pg.rds.aliyuncs.com:5432/agent_db?currentSchemapublicstringtypeunspecifiedreWriteBatchedInsertstrue username: your_user password: your_password driver-class-name: org.postgresql.Driver hikari: maximum-pool-size: 50 minimum-idle: 10 connection-timeout: 30000 idle-timeout: 600000 max-lifetime: 1800000 # 关键开启故障转移 connection-init-sql: SELECT 1 # 关键设置 socket timeout防网络抖动 socket-timeout: 100003. JSONB 字段映射EntityData TableName(sessions) public class SessionEntity { TableId(type IdType.AUTO) private UUID sessionId; private String userId; // 使用 TableField 注解指定 JSONB 类型处理器 TableField(value context_jsonb, typeHandler JsonbTypeHandler.class) private MapString, Object context; private LocalDateTime lastActiveTime; // 自定义 TypeHandler 处理 JSONB public static class JsonbTypeHandler extends BaseTypeHandlerMapString, Object { Override public void setNonNullParameter(PreparedStatement ps, int i, MapString, Object parameter, JdbcType jdbcType) throws SQLException { String json new ObjectMapper().writeValueAsString(parameter); PGobject pgObject new PGobject(); pgObject.setType(jsonb); pgObject.setValue(json); ps.setObject(i, pgObject); } // ... getNullableParameter 实现略 } }4. 向量查询封装ServiceService public class VectorSearchService { Autowired private JdbcTemplate jdbcTemplate; /** * 在 documents 表中搜索与 queryEmbedding 最相似的 topK 条记录 */ public ListDocument searchByEmbedding(float[] queryEmbedding, int topK) { String sql SELECT id, title, content, 1 - (embedding ?) as similarity FROM documents ORDER BY embedding ? LIMIT ?; // 将 float[] 转为 PolarDB 向量格式{0.23,-0.45,0.89} String vectorStr Arrays.stream(queryEmbedding) .mapToObj(String::valueOf) .collect(Collectors.joining(,, {, })); return jdbcTemplate.query(sql, new Object[]{vectorStr, vectorStr, topK}, (rs, rowNum) - new Document( rs.getString(id), rs.getString(title), rs.getString(content), rs.getFloat(similarity) )); } }4. 常见问题与避坑指南来自真实战场的血泪经验4.1 “为什么我的 JSONB 查询这么慢”——索引失效的三大陷阱JSONB 查询慢90% 的原因是索引没生效。我整理了三个最隐蔽的陷阱陷阱一路径表达式不匹配索引现象为context_jsonb-tags建了 GIN 索引但查询WHERE context_jsonb {tags: [debug]}很慢。原因操作符要求 JSONB 值完全匹配而-tags索引只加速对tags字段的提取。正确做法是为整个 JSONB 字段建索引CREATE INDEX idx_sessions_context ON sessions USING GIN (context_jsonb);然后用WHERE context_jsonb {tags: [debug]}。验证执行EXPLAIN (ANALYZE, BUFFERS) SELECT ...看执行计划中是否有Bitmap Heap Scan on sessions和Bitmap Index Scan on idx_sessions_context。陷阱二JSONB 值过大导致索引膨胀现象context_jsonb字段平均大小 2MB建 GIN 索引后索引体积是表的 5 倍写入变慢。原因GIN 索引会对 JSONB 中每个键值对、每个数组元素都建立倒排索引数据越大索引越臃肿。解法只索引关键路径。例如若只查tags和topic则建部分索引CREATE INDEX idx_sessions_context_partial ON sessions USING GIN ((context_jsonb-tags), (context_jsonb-topic));。陷阱三JSONB 中混用字符串与数字现象context_jsonb中{age: 25}字符串和{age: 25}数字并存查询WHERE context_jsonb {age: 25}无法命中字符串型数据。原因JSONB 的是严格类型匹配。解法统一数据类型或在应用层转换。我们强制约定所有数值型字段在 JSONB 中存为数字字符串型存为字符串绝不混用。4.2 “Agent 突然卡住日志显示连接超时”——连接池与事务的生死线Agent 的高并发特性让连接池成为最脆弱的环节。我遇到过三次“连接雪崩”案例一连接泄漏现象Agent 运行 2 小时后active_connections持续上涨至 4000新请求全部超时。根因一个Transactional方法中调用了外部 HTTP 服务该服务响应慢30s导致事务长时间持有连接。而连接池最大连接数为 5050 个连接被占满后续请求排队最终超时。解法① 为所有外部调用加TimeLimiterResilience4j② 设置事务超时Transactional(timeout 5)③ 连接池max-lifetime设为 1800000ms30 分钟强制回收陈旧连接。案例二长事务阻塞 DDL现象执行ALTER TABLE sessions ADD COLUMN metadata_jsonb JSONB时该 DDL 语句卡住 10 分钟所有写入请求超时。根因PostgreSQL 的 DDL 需要获取ACCESS EXCLUSIVE锁而一个长事务如一个未提交的UPDATE sessions SET ...正持有ROW EXCLUSIVE锁两者冲突。解法① 禁止在 Agent 核心链路中使用长事务② 对 DDL 操作使用 LOCK