接手 PolarDB-X 集群的前三个月我几乎把时间都耗在两类事情上一是帮业务同学写那些跨分片聚合的查询 SQL二是半夜爬起来处理慢 SQL 告警。单机 MySQL 上那套“登录上去开个 slow log 看看、缺索引就加个索引”的运维流在分布式架构里完全不够用——一条 SQL 慢可能是分片键选得不对可能是全局索引缺失也可能是某个节点的资源水位已经触顶。这些判断如果全靠 DBA 人肉完成每天能处理的工单非常有限更别提每个工单背后还在持续产生新的慢查询。这篇文章想分享的是我自己搭建的一套 PolarDB-X AI 助手它把三个能力做成了一个整体自然语言转 SQL让业务同学直接说人话查数据智能诊断让慢 SQL 出现后能自动完成从指标采集到根因分析的链路方案推荐让诊断结果最终落到可执行的优化动作上。标题里“方案推荐”这四个字包含两层意思——既推荐怎么查也推荐怎么改。如果你是负责 PolarDB-X 运维的 DBA或者是想在企业内部落地数据库智能助手的开发者这篇文章里的架构思路、Prompt 设计、踩坑记录应该都能直接用上。1. 单机运维的拿手好戏为什么到 PolarDB-X 上就不灵了1.1 分布式架构新增的三个隐性成本单机 MySQL 排查慢查询的路径很固定开慢日志拷出 SQLEXPLAIN 看执行计划缺索引就加索引。这套流程在 PolarDB-X 上仍然成立但只是第一步。分布式数据库把“一条 SQL 的执行路径”彻底拉长了至少多出三处单机时代不需要关心的环节。第一是分区裁剪是否生效。PolarDB-X 默认按分片键路由如果查询条件里没有带分片键即使有索引也可能要走全部分片的扫描执行计划里 Scan 的分片数直接决定 RT。这个问题在业务初期往往不明显等数据量上来之后一次全分片扫描的代价会成倍放大。第二是全局二级索引GSI是否存在。局部索引只在单个分片内有效跨分片查询如果没有 GSI数据库就要把每个分片的数据拉上来做聚合。PolarDB-X 的架构里GSI 是解决“非分片键查询”的核心手段但很多从单机 MySQL 迁移过来的同学根本没有这个概念习惯性地只看得见普通索引。第三是分布式事务和锁的放大效应。单库死锁影响面有限PolarDB-X 里一个热点分片上的锁竞争会传导到多个关联事务表现为业务侧“偶发超时”。这种问题如果你只盯着慢日志往往看不到全貌。这些维度靠人肉看监控是能发现的但效率太低。我见过最典型的一个案例业务方上报“订单查询变慢”DBA 查了一下午最后发现是某天的营销活动把所有流量打到了一个用户分片上——分片键是 buyer_id活动用户集中在一个买家身上。这类问题不是索引能解决的需要结合分片数据分布、流量特征、SQL 访问模式综合判断。这就是我决定做 AI 助手的直接动机。1.2 AI 助手到底解决谁的什么问题动手之前我把需求方分成了三类每类的痛点完全不同产品形态也因此不一样。业务研发的痛点是不熟悉 SQL或者熟悉 SQL 但不了解 PolarDB-X 的分片机制写出来的查询经常全分片扫描。他们需要的是“用自然语言描述需求直接得到能跑且跑得快的 SQL”。对他们来说AI 助手是提效工具。DBA 和运维同学的痛点是被重复的慢 SQL 治理淹没每个排查动作都要在多个控制台之间切换。他们需要的是“诊断结论 优化方案”的自动化输出而不是再来一个监控大盘。对他们来说AI 助手是减负工具。架构和研发负责人的痛点是需要知道集群当前最大的隐患是什么、该投入资源优化哪一块。他们需要的是周期性诊断报告和分级建议。对他们来说AI 助手是决策辅助。三类需求统一成一个产品形态一个具备自然语言理解能力的智能体前端接对话和工单后端接 PolarDB-X 的诊断数据和控制能力。对应到功能上就是标题里说的三块——自然语言 SQL、智能诊断、方案推荐。2. 整体架构AI 助手不是“套壳聊天框”而是一条完整链路2.1 四个核心模块的划分我做的这套系统没有采用“一个聊天框 一个模型”的简单形态而是拆成了四个模块让每个模块职责单一、可以独立迭代。接入层负责对话界面、工单系统对接、权限认证。所有用户请求先到这里校验身份和权限后才往下走。语义层NL2SQL把自然语言查询转换成 SQL。输入是用户问题 表结构元数据输出是候选 SQL 和一句人话解释。诊断层定期从 PolarDB-X 拉取慢日志、监控指标、锁等待数据用规则引擎做粗筛再用大模型做根因归因最终输出诊断报告。推荐层承载优化方案的生成、分级、推送给用户并记录方案执行后的效果数据形成闭环。一个典型的同步请求流程是这样用户在对话界面输入“查一下最近七天每个卖家的订单金额”接入层把请求转给语义层语义层从元数据库里找到 orders、order_detail 等表结构连同用户问题一起打包给大模型生成候选 SQL然后这条 SQL 会先到诊断层做 EXPLAIN 校验确认能跑、且执行计划不是全分片扫描后才返回给用户。诊断和推荐是异步任务。每天凌晨诊断层拉取昨天的慢日志和监控数据跑规则引擎命中规则的问题再交给大模型分析根因产出优化建议后推送到推荐层。告警触发时也会走同一套链路只是这次是实时执行。模块之间通过消息队列解耦诊断任务跑多久都不会阻塞对话请求。2.2 模型选型与元数据同步到底怎么权衡选型上我走了两条路并行的策略。在线 NL2SQL 场景我优先用大模型 API响应快、语义理解强适合处理开放性的自然语言到 SQL 的映射问题。诊断分析场景则优先用“小参数模型 规则引擎”的组合因为诊断链路里大部分判断是确定性的——比如“某个分片的 QPS 超过阈值”“某条 SQL 的扫描行数超过 100 万”这些用规则表达既快又稳大模型只负责处理规则命中不了的部分比如“为什么这个分片会变成热点”。这样做既能控制调用成本也能保证诊断结果不飘。另一个很容易被忽略的点是元数据同步。PolarDB-X 的 schema 是动态变化的业务加字段、加索引、调整分片都很频繁。AI 助手必须有一套稳定的元数据同步机制定时把表结构、分片键、全局索引信息同步到本地知识库。我踩过的坑是刚开始没有做同步模型拿到的是两周前的表结构生成的 SQL 里引用了一个已经被删掉的字段前端直接报错。后来改成每天凌晨通过 information_schema 全量刷新NL2SQL 的准确率明显上了一个台阶。3. 自然语言转 SQL核心是让模型“看懂”PolarDB-X 的特殊语法3.1 Schema 上下文怎么构建做过 NL2SQL 的同学都知道模型能不能生成正确 SQL很大程度取决于你喂给它的表结构信息够不够完整。单机数据库只需要表名、字段名、类型、注释但 PolarDB-X 还必须额外标注两个关键信息分片键和全局二级索引。分片键决定了 SQL 能不能做分区裁剪。同样的查询条件里带 buyer_id 和不带 buyer_id执行计划可能一个扫描 1 个分片一个扫描 64 个分片。GSI 信息也很重要模型知道某个非分片键字段上有 GSI就会优先用 GSI 字段做过滤条件而不是傻乎乎地全分片扫描。我构建 schema 上下文的做法分三步。第一步从 information_schema 读取所有表的字段信息第二步用 SHOW FULL CREATE TABLE 拿到完整的建表语句这里面自带分片键和 GSI 信息第三步把这些信息解析成结构化的 JSON拼进 Prompt。-- 查看 PolarDB-X 表的分区信息 SELECT TABLE_NAME, PARTITION_NAME, PARTITION_METHOD FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA trade_db;-- 拿到完整建表语句自带分片键和 GSI 定义 SHOW FULL CREATE TABLE orders;import pymysql import json conn pymysql.connect( hostpolardbx-endpoint, port3306, userai_reader, password******, databasetrade_db, ) with conn.cursor() as cur: cur.execute(SHOW FULL CREATE TABLE orders) row cur.fetchone() # row[1] 就是完整建表语句 schema_info {table: orders, ddl: row[1]} print(json.dumps(schema_info, ensure_asciiFalse, indent2))实际在 Prompt 里我不会直接放大段建表 DDL而是只放结构化摘要。原因是 DDL 里包含太多模型不需要的存储参数容易干扰判断。摘要长这样[orders] - id BIGINT 主键 - buyer_id BIGINT, 分片键 - seller_id BIGINT - amount DECIMAL(10,2) - status VARCHAR(20) - create_time DATETIME - 全局二级索引: idx_seller_id(seller_id), idx_create_time(create_time) - 说明: 按 buyer_id 哈希分片共 64 个分片3.2 Prompt 模板与 Few-shot 设计Prompt 是整个 NL2SQL 链路里投入产出比最高的环节。我前前后后改了十几版最终稳定下来的模板包含四个部分角色定义、表结构摘要、生成约束、Few-shot 示例。角色定义要让模型进入“PolarDB-X 专家”的状态。生成约束里我会强调三条只生成 SELECT 语句过滤条件里优先用分片键或 GSI 字段输出只给 SQL不要解释。你是 PolarDB-X 数据库的 SQL 专家。PolarDB-X 兼容 MySQL 协议但具有分布式特性。 请根据表结构摘要把用户的自然语言查询转换为 SQL。 表结构 {structured_schema} 生成要求 1. 只生成 SELECT 语句绝不生成 INSERT/UPDATE/DELETE/DDL。 2. 如果查询条件包含分片键必须作为第一个过滤条件。 3. 没有分片键条件时优先使用全局二级索引字段避免全分片扫描。 4. 涉及聚合时尽量在数据库内完成不要先查出明细再在应用层聚合。 5. 只输出 SQL 本身不要附加任何解释。 参考示例 问查最近7天每个卖家的订单总金额只看已支付订单。 答SELECT seller_id, SUM(amount) AS total_amount FROM orders WHERE status PAID AND create_time NOW() - INTERVAL 7 DAY GROUP BY seller_id; 用户问题{question}Few-shot 示例的选取很重要。我最初放的示例是网上公开的 NL2SQL 数据集效果一般因为那些示例和 PolarDB-X 的分片场景无关。后来我改成从真实慢日志里挑典型问题做示例比如“按非分片键查询”和“跨分片聚合”模型很快就学会了“先看有没有 GSI”这个思维习惯。3.3 EXPLAIN 校验与只读兜底大模型生成的 SQL 不能直接交给用户执行这在生产环境是铁律。我的做法是加一道“EXPLAIN 校验”关卡校验不通过就把 SQL 打回重生成最多重试两次。generated_sql llm_call(prompt) # 模型生成的 SQL # 强制只取第一条 SELECT if not generated_sql.strip().upper().startswith(SELECT): raise ValueError(模型没有生成 SELECT 语句重新生成) # EXPLAIN 校验 with conn.cursor() as cur: cur.execute(fEXPLAIN {generated_sql}) plan cur.fetchall() # 这里检查 plan 中是否出现全分片扫描 # PolarDB-X 的 EXPLAIN 结果里会包含分片数量信息校验逻辑有两个重点。第一个是语法校验模型偶尔会生成 PolarDB-X 不支持的语法EXPLAIN 会直接报错这时候打回重生成即可。第二个是执行计划合理性校验我会看 EXPLAIN 结果里的扫描分片数如果超过了总分片数的一半就判定为“可能有全分片扫描风险”需要重写或者至少给用户一个提示。只读兜底同样不能少。AI 助手的数据库账号我用的是最小权限账号只授权了 SELECT。同时应用层还要再做一道 SQL 黑名单检测DROP、TRUNCATE、ALTER、DELETE、UPDATE 这些关键字统统拦下来模型生成的 SQL 里如果出现多个语句只取第一个 SELECT丢弃其余内容。两道防线叠加我才能放心地把 SQL 展示给业务同学。4. 智能诊断链路从慢日志到根因分析4.1 诊断数据的采集口径自然语言 SQL 只是 AI 助手的一半另一半是智能诊断。诊断的第一步是拿到准确的数据否则后面全是空谈。我采集的数据分四类。第一类是慢日志PolarDB-X 的慢日志里除了 SQL 文本还有执行时间、扫描行数、返回行数、物理分片 ID这些字段是后续判断“是不是全分片扫描”的关键证据。第二类是监控指标包括每个计算节点的 CPU、内存、连接数、QPS、RT以及每个数据分片的水位和读写 QPS。第三类是锁等待数据通过 information_schema 里的 innodb_trx 和 innodb_lock_waits 视图拿。第四类是元数据主要是表的分片键、GSI、表行数估计。采集频率上慢日志和监控指标我建议至少每分钟拉一次锁等待数据可以降低到每 5 分钟一次。这里有一个容易被忽略的坑PolarDB-X 的慢日志表如果数据量太大查询本身也会变慢必须定期归档。4.2 规则引擎 大模型的混合诊断模式很多做 AI 诊断的项目容易犯一个错误把所有问题都丢给大模型。实际上直接问大模型“集群有没有问题”它只能给出泛泛的回答因为大模型对当前集群的状态一无所知。正确做法是先用规则引擎把“事实”找出来再让大模型基于事实做归因。我的规则引擎里维护了几组固定的检查项检查项触发条件初步结论高 RT 慢 SQL执行时间 200ms且同模板 SQL 出现频率 50 次/小时高频慢 SQL全分片扫描EXPLAIN 中扫描分片数 总分片数分片键或 GSI 使用不当热点分片某个分片 QPS 是平均值 3 倍以上持续 5 分钟数据倾斜或热点流量锁等待innodb_lock_waits 出现持续 3 分钟以上的锁等待锁竞争容量水位某分片磁盘使用率 80%容量风险规则引擎命中后会把“事实快照”拼成一个结构化的问题描述再丢给大模型。大模型的任务不是发现问题而是解释问题为什么发生、以及应该往哪个方向排查。比如规则引擎检测到“orders 表上的 SELECT 全分片扫描”大模型的分析结果是“该 SQL 的过滤条件是 seller_id不是分片键且 seller_id 上无 GSI建议创建 GSI 或改造查询条件”。混合诊断的核心价值在于规则引擎保证了下限大模型拉高了上限。规则不会因为状态波动给出离谱结论大模型又能处理规则覆盖不到的复杂场景。4.3 一次完整诊断案例拆解说一个实际跑通过的全流程案例。某天下午告警系统触发orders 表相关查询 RT 上涨了 10 倍。诊断链路自动启动。第一步规则引擎从慢日志里拉最近 15 分钟的慢 SQL发现一个高频模板SELECT * FROM orders WHERE seller_id ? AND status PAID ORDER BY create_time DESC LIMIT 20执行时间中位数 1200ms。同时监控指标显示所有 64 个分片的 QPS 都上涨但没有单一热点分片。第二步规则引擎进一步对这条 SQL 做 EXPLAIN发现扫描分片数是 64即全分片扫描。这时初步结论已经清晰非分片键查询 无 GSI。第三步大模型介入做归因。它看到的事实是seller_id 上有局部索引但没有全局二级索引orders 表按 buyer_id 分片该 SQL 被店铺维度的业务高频调用。结论是局部索引在单分片内有效但跨分片查询时每个分片都要各自索引扫描再合并所以慢。最终推荐层给出的方案是创建 GSIidx_seller_status(seller_id, status)。DBA 确认后在低峰期执行第二天同类 SQL 的 RT 从 1200ms 降到 8ms慢日志里这条模板消失。这个案例让我确认了一件事只要规则引擎能提供准确的事实快照大模型的归因分析是可以被信任的而且诊断速度远超人肉排查。5. 方案推荐不是空话建议而是可执行的优化清单5.1 优化方案的分级与类型诊断是为了给出方案方案不能是“建议优化索引”这种空话。我的推荐层会把方案分成几个等级每个等级对应不同的执行动作和风险说明。第一类是紧急处理类对应 P0。典型场景是容量即将打满、热点分片导致整个集群抖动。这类方案通常不是 SQL 层面能解决的需要扩容、切流或者调整业务入口限流执行风险高必须走变更评审。第二类是高频 SQL 优化类对应 P1。典型场景就是上面案例里的全分片扫描。动作包括创建 GSI、改写 SQL 条件、把大查询拆成多个小查询等。这个级别的方案风险和收益都中等落地后效果最明显。第三类是常规优化类对应 P2。比如 SELECT 返回了不需要的大字段、GROUP BY 没有索引支持导致的临时表排序、隐式类型转换导致索引失效等。这类方案风险低可以每天批量处理。方案的类型也不是只有“加索引”一种。我总结过AI 助手推荐的方案大概覆盖这些类别索引建议局部索引、GSI、SQL 改写建议、表结构设计建议分片键选择、字段类型调整、事务拆分建议、参数调优建议连接池大小、超时设置。分类的价值在于推送方案时能自动匹配到对的人——SQL 改写建议推给研发参数调优建议推给 DBA。5.2 推荐的置信度判断与效果回滚AI 推荐的方案不能百分之百信任必须带上置信度标签。我的推荐层会给每个方案打一个“推荐置信度”计算依据有三个维度规则证据的充分程度、同类问题历史处理记录的一致性、大模型归因结论的语言确定性。置信度高的方案比如“创建 GSI 明确的索引字段组合”系统可以自动生成变更脚本直接推给 DBA 审批。置信度低的方案系统只输出分析过程不给出强结论需要 DBA 人工介入。这里必须说一个我踩过的坑。有一次规则引擎检测到某张表没有主键自动推荐“添加自增主键”。从规则角度讲这个建议没错但那张表的分片键本来是业务主键强行加自增主键会影响数据分布。结果是 DBA 看到方案后产生了争议最后人工确认才解决。从那以后我在推荐层加了一条规则凡是涉及表结构变更的方案必须经过一轮“分片键冲突检测”检测不通过就自动降级为低置信度。效果回滚也很重要。每个方案执行前推荐层会记录当前 SQL 的 RT 和扫描行数作为基线执行后一周内持续对比新数据。如果效果变差系统会触发回滚建议。这套机制虽然简单但能让研发和 DBA 对 AI 推荐产生信任感。5.3 从推荐到工单的闭环设计方案推荐如果不落到执行环节就只是一个“高级公告板”。我把推荐层和工单系统做了打通。每次诊断触发后推荐层自动生成一张诊断工单内容包括问题现象、规则命中的证据、大模型的归因分析、推荐方案、置信度、预期效果。工单推送到钉钉/企微相关人可以直接在聊天窗口里审批。审批通过后方案会自动转成可执行的变更脚本。对于 GSI 创建这类低风险操作变更脚本会进入低峰期自动执行对于扩容这类高风险操作必须人工二次确认。工单的流转状态也会回写到诊断系统。如果某个方案被执行了后续同类问题再次出现时规则引擎会优先检查“之前创建的 GSI 是否还在、是否生效”避免重复推荐同一个已执行的方案。这个闭环让系统越用越聪明。6. 落地过程中的坑与经验6.1 NL2SQL 的错误率远比想象中高做之前我对大模型生成 SQL 的能力过于乐观实测下来在复杂查询场景下首次生成的正确率只有 70% 出头。错误主要集中在几个地方多表 JOIN 时搞错关联字段、聚合粒度不对、漏掉 WHERE 条件里的时间范围。我后来的解决方式不是继续调 Prompt而是加了“两轮生成 一轮校验”的流程。第一轮让模型直接生成 SQL第二轮把第一轮的 SQL 和用户的自然语言一起返回给模型让它自查一遍“SQL 是否完全覆盖了用户需求”。这个简单的“自检”机制把正确率提升了差不多 10 个百分点。再叠加 EXPLAIN 执行计划校验最终能进入用户视野的 SQL 基本都是可以跑通的。给后来者的建议是不要指望一次生成就完美。NL2SQL 在真实生产环境里的定位应该是“辅助生成、人工确认”尤其是 DELETE、UPDATE 这类有副作用的语句永远不要让模型全权操作。6.2 Schema 太大塞不进上下文怎么办真实业务库里可能有几百张表全部塞进 Prompt 不现实。上下文有限模型也会被无关表结构干扰。我的做法是两级路由。第一次请求只带所有表的“表名 注释”索引清单让模型判断这个问题涉及哪几张表确定目标表之后第二次请求再带上这几张表的完整结构信息和分片键、GSI 标注。这样大多数场景只需要 3 到 5 张表的完整结构就能生成 SQL上下文开销小准确率也高。另一个补充方案是高频表优先策略。统计过去 30 天被查询最多的 20 张表把它们完整结构常驻在上下文里低频表只给表名。日常业务查询大部分集中在少数表上这个策略很有效。6.3 权限边界AI 助手绝对不要碰的操作安全是 AI 助手能不能落地的底线。我的原则是AI 助手只做“读”和“建议”永远不做“写”和“执行”。具体到实现上数据库账号只授 SELECT这是第一道防线。应用层做 SQL 黑名单过滤这是第二道防线。高危 DDL 不管置信度多高都必须经过 DBA 工单审批这是第三道防线。前面提到的自动执行也只针对 CREATEGSI 这类低风险变更而且执行窗口固定、自动限流。另外所有 AI 助手生成的 SQL 和推荐方案都要留痕。我这里保留了完整的审计日志包括谁问了什么问题、模型生成了什么 SQL、最终有没有被使用。这个留痕机制在事后追溯时极其重要尤其是出问题需要定位“是不是 AI 建议导致的”。6.4 效果评估怎么证明这套系统真的有用搭一套系统不难难的是证明它有用。我做效果评估时没有只看“模型准确率”而是盯着两个业务侧的指标。第一个是慢 SQL 工单的平均处理时长。上线前从收到告警到给出优化建议平均要 45 分钟上线后AI 助手能在一分钟内生成诊断报告DBA 只需要确认和执行平均处理时长降到 22 分钟。第二个是线上慢 SQL 数量月环比变化。系统跑了两个月后高频慢 SQL 数量下降了约 60%因为 AI 推荐创建的一批 GSI 实打实地消灭了全分片扫描。评估过程有个容易忽略的细节需要一份固定的标注样本集。我提前让人工标注了 200 条“问题描述 - 正确 SQL/正确诊断结论”的样本每次升级模型或调整 Prompt 后都在这个样本集上回归一遍防止“修了一个问题、弄坏了三个场景”。没有这个样本集你很难判断系统的优化是真实进步还是碰运气。最后再分享一个小技巧。PolarDB-X 这类分布式数据库的 AI 助手不要一开始就做太多功能。先跑通“慢 SQL 诊断 GSI 推荐”这一个闭环让 DBA 看到实打实的效果再去扩展 NL2SQL 和工单自动化。技术的信任感和业务价值都是从一个一个具体问题上积累起来的这套系统现在还在持续迭代下一步我打算把运维巡检日报也接进来让 AI 助手从一个“被动的解答者”变成“主动的巡检员”。