当前位置: 首页 > news >正文

我用AI生成的SQL,差点在生产库上跑了一整夜

我用AI生成的SQL,差点在生产库上跑了一整夜

目录

  • 凌晨的告警短信
  • 那段"看起来没问题"的SQL
  • EXPLAIN输出告诉我真相
  • 为什么AI不关心你的索引
  • 给AI加规则后重新生成
  • 我现在怎么用AI写SQL

凌晨的告警短信

那天凌晨两点,手机连续收到四条阿里云RDS告警:"CPU使用率超过90%","活跃连接数超过200","慢查询阈值触发"。我打开DMS连上去一看,show processlist里躺着一条SQL,Time列显示已经跑了23分钟,state是Sending data

这条SQL是我下午让AI生成的。

业务场景不复杂:运营要一个数据报表,统计最近30天各商品类目的订单转化率。我懒得手写这条跨五张表的统计查询,就把需求描述贴给了AI:"写一条MySQL查询,统计近30天每个商品类目的订单转化率,需要关联用户表、商品表、类目表、订单表和订单明细表,按转化率降序排列。"

AI很快给出了结果,我在测试环境跑了一下,数据量小的时候返回很快,看起来没问题。代码评审的时候也没人觉得有毛病——五表JOIN在报表场景太常见了。

那段"看起来没问题"的SQL

AI产出的SQL大概是这个结构(脱敏后):

sql SELECT c.category_name, c.category_id, COUNT(DISTINCT o.order_id) AS total_orders, COUNT(DISTINCT oi.order_id) AS converted_orders, ROUND(COUNT(DISTINCT oi.order_id) * 100.0 / COUNT(DISTINCT o.order_id), 2) AS conversion_rate FROM orders o LEFT JOIN users u ON o.user_id = u.user_id LEFT JOIN order_items oi ON o.order_id = oi.order_id LEFT JOIN products p ON oi.product_id = p.product_id LEFT JOIN categories c ON p.category_id = c.category_id WHERE o.create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY) AND o.order_status IN (1, 2, 3, 5) AND u.user_type = 'NORMAL' GROUP BY c.category_id, c.category_name ORDER BY conversion_rate DESC;

语法没问题,格式也工整。问题出在它"不知道"的东西上。

EXPLAIN输出告诉我真相

我在生产只读库上跑了EXPLAIN,结果让人头皮发麻:

| table | type | key | rows | Extra | |-------|------|-----|------|-------| | orders | range | idx_create_time | 860000 | Using where; Using temporary; Using filesort | | users | eq_ref | PRIMARY | 1 | Using where | | order_items | ALL | NULL | 1200000 | Using where; Using join buffer | | products | eq_ref | PRIMARY | 1 | NULL | | categories | eq_ref | PRIMARY | 1 | NULL |

order_items表走了全表扫描,rows估算120万行。生产库里order_items表有接近两千万行数据。这个查询在生产上跑完估计要超过40分钟。

问题出在哪里?AI不知道这张表的实际数据分布。它不可能知道——

order_items表缺少必要的索引。order_id字段虽然在order_items表里,但这个字段没有单独的索引,它只是联合主键(order_id, item_id)的一部分。MySQL优化器在某些情况下用不到联合主键的最左前缀。

隐式类型转换。oi.product_id = p.product_id看起来正常,但order_items.product_idvarchar(32)products.product_idbigint(20)。这种类型不一致在数据量小的时候无所谓,数据量大时索引直接失效。

N+1式统计。COUNT(DISTINCT oi.order_id)在大数据量下的去重计算代价极高。AI可以写出正确的SQL语法,但它不具备"这条SQL在生产库上跑会不会出问题"的判断力。

为什么AI不关心你的索引

这里有个根本性的问题要说清楚:AI生成SQL时看到的是"表结构"和"需求描述",它看不到——

生产中每张表的实际数据量和增长率。一张表有1万行和有2000万行,最优查询策略完全不同。

索引的实际选择性与碎片率。建了索引和索引真的被用到是两码事。order_items表上明明有联合主键,但实际执行计划里MySQL就是选了全表扫描。

MySQL优化器的版本差异。同样的SQL在MySQL 5.7和8.0上执行计划可能完全不同。AI默认参考的是通用文档,不会针对你的具体版本。

给AI加规则后重新生成

发现问题后我没有自己改SQL,而是重新问AI,这次加了规则:

"重写这条SQL,注意:order_items表有2000万行,product_id是varchar类型不是数值类型,避免DISTINCT在2000万行上的性能问题,先聚合再JOIN。"

这次AI生成的SQL好得多:

sql SELECT c.category_name, c.category_id, stats.total_orders, stats.converted_orders, ROUND(stats.converted_orders * 100.0 / stats.total_orders, 2) AS conversion_rate FROM ( SELECT p.category_id, COUNT(DISTINCT o.order_id) AS total_orders, COUNT(DISTINCT CASE WHEN oi.order_id IS NOT NULL THEN o.order_id END) AS converted_orders FROM orders o JOIN users u ON o.user_id = u.user_id AND u.user_type = 'NORMAL' LEFT JOIN order_items oi FORCE INDEX(idx_order_id) ON o.order_id = oi.order_id LEFT JOIN products p ON oi.product_id = p.product_id WHERE o.create_time >= DATE_SUB(NOW(), INTERVAL 30 DAY) AND o.order_status IN (1, 2, 3, 5) GROUP BY p.category_id ) stats JOIN categories c ON stats.category_id = c.category_id ORDER BY conversion_rate DESC;

改进点很实在:

用子查询先聚合再JOIN,减少了categories表参与中间结果集。

加了FORCE INDEX(idx_order_id)提示,因为我知道order_items表上有个单独的idx_order_id索引(AI不知道,但我说了它就会用)。

把类型不一致的问题明确告诉AI后,它不会再犯同样的错。

我现在怎么用AI写SQL

这件事之后,我写SQL的流程变成了这样:

先把需求按"表名 + 实际行数 + 索引列表 + 字段类型"的格式丢给AI。比如:

orders: 860万行, 索引idx_create_time(create_time), idx_user_status(user_id, order_status) order_items: 2000万行, 索引idx_order_id(order_id), 联合主键(order_id, item_id) product_id在order_items中是varchar(32),在products中是bigint(20) 需求:统计近30天各商品类目的订单转化率

然后等AI出SQL,我自己跑EXPLAIN看执行计划。如果type列出现ALL,就要追问AI:"这个表2000万行你让它全表扫?换个写法。"

几轮下来,AI产出的SQL质量明显提高。因为它从我的反馈里学到了"大表不能用ALL扫描"、"字段类型不同会导致索引失效"这些约束。

这不是AI变聪明了,是我给的上下文变丰富了。

我后来在团队里做了个分享,标题就叫"AI不知道你的表有多大"。分享完后一个同事说:"这不就是欺负AI没见过生产数据嘛。"我说对,所以你得替它见。

写SQL这件事上,AI能帮你省掉80%的敲键盘时间,但剩下的20%——理解数据规模、看懂执行计划、避开隐式类型转换——还得你自己来。这20%才是区分"能用"和"出事故"的关键。

http://www.gsyq.cn/news/1505503.html

相关文章:

  • 终极指南:使用ChromePass高效管理浏览器密码的完整方案
  • 多模态嵌入技术:模态间隙解析与优化策略
  • PMBOK第七版视角:项目整合管理的核心实践与价值交付
  • 大模型之交互式应用(理论篇)
  • GCC完全指南
  • 企业级数据集成平台架构设计与技术实现深度解析
  • 从零构建一个AI驱动的英语单词默写小程序:技术架构全解析
  • PostHog产品分析平台终极指南:从零到精通的开源数据分析解决方案
  • 国内合规催化燃烧设备厂家实测排行权威盘点 - 起跑123
  • 郑州名包回收怎么选?多家门店行情对比参考 - 禹竞
  • 2026年众智商学院SCMP供应链管理专家报名:质量管理人员怎么学?模块选择、资料领取和课程咨询入口 - 众智商学院职业教育
  • CANN技术解读|metadef元数据结构与模型定义规范——深度解析昇腾CANN计算架构中基础数据层的核心设计
  • 通俗易懂掌握树与二叉树:定义、核心概念与JS实现遍历
  • 2026年6月最新版驻马店第三方CMACNAS甲醛检测治理机构口碑名单:万清CMA检测中心等5家公司深度测评万清CMA检测中心TOP1推荐 - 一修哥咨询
  • Java IO流总结
  • 2026年6月最新版遵义第三方CMACNAS甲醛检测治理机构口碑名单:万清CMA检测中心等5家公司深度测评万清CMA检测中心TOP1推荐 - 一修哥咨询
  • 深度解码:为什么你的PCSX2跑不满60帧?3个被忽视的性能瓶颈揭秘
  • 2026山东五恒空调厂家实力排行:核心维度实测对比 - 起跑123
  • 从LXC到Docker:深入解析容器技术的演进、核心原理与选型指南
  • 2026年6月电子线生产厂家口碑推荐,行业内电子线源头厂家,耐化学腐蚀,延长使用寿命 - 品牌推荐师
  • 超元力玻璃剧场轻量化落地体系,构筑文旅业态长效运营新基石
  • 昆明社区回收店测评:家门口小店靠谱吗?实测结果意外 - 奢侈品回收评测
  • 华硕笔记本性能调优神器:5步掌握G-Helper完整使用指南
  • 2026 韶关黄金回收价位盘点 全城实体门店综合测评 - 靖昱黄金回收
  • 从零到一:手把手教你打造STC89C52RC最小系统板
  • 国内激光清障仪主流厂家实力排行及核心资质盘点 - 奔跑123
  • 面向企业知识库问答的 RAG 落地实践:大模型如何从“会聊天”变成“懂业务”
  • 如何在10分钟内彻底掌握Etcher镜像烧录工具的核心用法
  • SD-PPP:Photoshop AI插件终极免费指南,让设计创作更智能高效
  • 2026年PCBA加工丨smt加工丨贴片加工行业十大靠谱工厂榜单出炉,广东东莞这家企业凭什么入选? - 变量人生001