DeepSeek V4 实战:自然语言生成 SQL + 智能优化引擎

引言

DS V4实战篇:

DeepSeek V4 + Spring Boot 3 + JDK 21 :万字实战教你打造AI智能编码助手

DeepSeek V4 实战:打造一个智能 Java 项目源码分析助手

在上一篇文章中,我们利用 DeepSeek V4 的百万上下文能力构建了项目源码分析助手。本文将实验另一个高频场景:自然语言转 SQL

业务人员写复杂 SQL 困难,开发人员手写的 SQL 可能索引缺失、全表扫描、性能低下。如果有一个工具,你只需要输入中文需求:"查询近 30 天每个品类的销售额排行,排除退货订单",它就能自动生成 SQL,并基于数据库真实执行计划给出优化建议和索引 DDL,这样是不是就很爽了!

本文将从零到一打造这样一个 SQL 智能生成与优化引擎,技术栈依然是前两章用到的 Java 21 + Spring Boot 3 ,核心 AI 能力由 DeepSeek V4 提供。前端提供一个简洁的 H5 页面,你输入需求,选择数据库方言,一键生成 SQL 并自动分析执行计划。

一、项目功能与架构

1.1 核心功能

模块 功能描述
自然语言 → SQL 输入中文需求,DeepSeek V4 生成对应方言的 SQL
SQL 执行与 EXPLAIN 通过 JDBC 执行 SQL 并获取执行计划
性能分析 将 EXPLAIN 结果送回 V4,识别索引缺失、全表扫描等问题
优化建议 输出优化后的 SQL + 索引创建 DDL
数据库元数据感知 读取表结构、现有索引,辅助 V4 生成更精准的建议

1.2 技术栈

组件 版本 用途
JDK 21 虚拟线程、文本块
Spring Boot 3.5.14 Web 框架
DeepSeek V4 deepseek-v4-pro/flash SQL 生成与优化
MySQL 8.0+ 测试数据库

1.3 项目结构

复制代码
deepseek-sql-optimizer/
├── pom.xml
├── src/main/java/io/github/iweidujiang/dsv4/sqloptimizer/
│   ├── SqlOptimizerApplication.java
│   ├── config/
│   │   ├── DeepSeekConfig.java
│   ├── controller/
│   │   └── SqlController.java
│   ├── service/
│   │   ├── SqlGenerateService.java
│   │   └── DatabaseMetadataService.java
│   ├── dto/
│   │   ├── SqlRequest.java
│   │   └── SqlResponse.java
│   └── util/
│       └── JdbcExecutor.java
├── src/main/resources/
│   ├── application.yml
│   ├── static/
│   │   └── index.html
│   └── db/
│       └── schema.sql

二、数据库准备

为了演示,我们来创建一个电商风格的数据库:品类表订单表

2.1 表结构 SQL(MySQL)

sql 复制代码
-- 创建数据库
CREATE DATABASE IF NOT EXISTS `demo-sql` DEFAULT CHARACTER SET utf8mb4;

USE `demo-sql`;

-- 品类表
CREATE TABLE `category` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(50) NOT NULL COMMENT '品类名称',
  `parent_id` INT DEFAULT 0 COMMENT '父品类ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- 订单表
CREATE TABLE `orders` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `order_no` VARCHAR(32) NOT NULL COMMENT '订单号',
  `category_id` INT NOT NULL COMMENT '品类ID',
  `amount` DECIMAL(10,2) NOT NULL COMMENT '订单金额',
  `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0-正常 1-退货',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `idx_category` (`category_id`),
  KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2.2 初始化数据

sql 复制代码
-- 品类数据
INSERT INTO `category` (`name`) VALUES ('电子产品'), ('服装'), ('家电'), ('图书');

-- 订单数据(过去30天随机生成,这里给一些示例)
INSERT INTO `orders` (`order_no`, `category_id`, `amount`, `status`, `create_time`) VALUES
('O001', 1, 299.00, 0, DATE_SUB(NOW(), INTERVAL 5 DAY)),
('O002', 1, 459.00, 0, DATE_SUB(NOW(), INTERVAL 12 DAY)),
('O003', 2, 129.00, 1, DATE_SUB(NOW(), INTERVAL 3 DAY)), -- 退货
('O004', 2, 399.00, 0, DATE_SUB(NOW(), INTERVAL 20 DAY)),
('O005', 3, 1999.00, 0, DATE_SUB(NOW(), INTERVAL 8 DAY)),
('O006', 3, 799.00, 0, DATE_SUB(NOW(), INTERVAL 15 DAY)),
('O007', 4, 55.00, 0, DATE_SUB(NOW(), INTERVAL 2 DAY)),
('O008', 4, 89.00, 0, DATE_SUB(NOW(), INTERVAL 25 DAY)),
('O009', 1, 1299.00, 0, DATE_SUB(NOW(), INTERVAL 1 DAY)),
('O010', 2, 259.00, 0, DATE_SUB(NOW(), INTERVAL 18 DAY));

数据量较小,足够演示。实际使用时可以自行扩充。

三、核心技术实现

3.1 让 DeepSeek 理解你的数据库

模型本身不知道你的业务库长什么样,所以我们需要在提示词中动态注入数据库元数据。元数据包括:所有表名、每张表的列名和类型、已有的索引信息。

核心服务 DatabaseMetadataService 利用 JDBC 的 SHOW TABLESSHOW COLUMNSSHOW INDEX 将这些信息拼接成文本。

java 复制代码
/**
 * 获取数据库中所有表名、列信息、现有索引,用于增强提示词
 */
public String getSchemaContext() {
    StringBuilder sb = new StringBuilder();
    try {
        // 获取所有表
        List<String> tables = jdbcTemplate.queryForList(
                "SHOW TABLES", String.class);
        for (String table : tables) {
            sb.append("表 ").append(table).append(":\n");
            // 列信息
            List<Map<String, Object>> columns = jdbcTemplate.queryForList(
                    "SHOW COLUMNS FROM " + table);
            for (Map<String, Object> col : columns) {
                sb.append("  列: ").append(col.get("Field")).append(" 类型: ").append(col.get("Type"))
                        .append(" 是否可空: ").append(col.get("Null")).append("\n");
            }
            // 现有索引
            List<Map<String, Object>> indexes = jdbcTemplate.queryForList(
                    "SHOW INDEX FROM " + table);
            if (!indexes.isEmpty()) {
                sb.append("  已有索引: ");
                String idxStr = indexes.stream()
                        .map(idx -> idx.get("Key_name").toString())
                        .distinct()
                        .collect(Collectors.joining(", "));
                sb.append(idxStr).append("\n");
            }
        }
    } catch (Exception e) {
        log.warn("获取元数据失败", e);
        return "无法获取数据库结构";
    }
    return sb.toString();
}

这样发送给 V4 的提示词就变成了:

复制代码
数据库结构如下:
表 category:
  列: id 类型: int 是否可空: NO
  列: name 类型: varchar(50) ...
  已有索引: PRIMARY
表 orders:
  列: id ... 列: category_id ... 列: amount ...
  已有索引: PRIMARY, idx_category, idx_create_time

用户需求:查询近30天每个品类的销售额排行,排除退货订单
数据库方言:mysql
请生成 SQL。

这种 "结构即上下文" 的方式,让 V4 生成的 SQL 能够准确匹配真实列名,而且能感知到现有索引,从而避免生成无法利用索引的 SQL。

3.2 生成 SQL:调用 V4 Pro 模型

提示词设计是重中之重。代码中设置对模型有两点硬性要求:

  1. 只输出 JSON,不要附带任何解释;
  2. 必须严格遵循指定的方言。

使用的 System Prompt 如下:

java 复制代码
private static final String GENERATE_SQL_SYSTEM = """
            你是一个资深 SQL 专家。根据用户的中文需求,生成符合指定方言的 SQL 查询语句。
            输出格式必须是 JSON:{"sql": "生成的SQL语句"}
            只输出 JSON,不要包含其他说明。
            """;

用户提示则包含了前面拼接的元数据、用户需求和方言。调用 V4 Pro 后,解析 JSON 得到 SQL。

由于代码中使用了 Spring AI 的 ChatClient,只需几行就能完成调用。

具体实现见 https://github.com/iweidujiang/deepseek-v4-playgroundSqlGenerateService.java

3.3 执行 EXPLAIN:获取真实执行计划

生成的 SQL 是否正确?性能如何?不能只靠模型猜测。

可通过 JdbcExecutor 直接执行 EXPLAIN + 生成的 SQL,将数据库的真实执行计划捕获下来。

例如 MySQL 返回的一行可能是:

复制代码
{id=1, select_type=SIMPLE, table=orders, type=ALL, possible_keys=idx_category, key=null, rows=10000, Extra=Using where}

type=ALL 意味着全表扫描,key=null 表示没有使用索引------这些都是优化的明确信号。

3.4 优化分析:交给 V4 Flash 模型

把原始需求、生成的 SQL 以及 EXPLAIN 结果三者打包,再次请求 DeepSeek,这次使用更便宜的 Flash 模型(成本只有 Pro 的 1/12 左右)。

System Prompt 要求输出 JSON:

json 复制代码
{
  "optimizedSql": "优化后的SQL语句",
  "indexDdl": "CREATE INDEX ...",
  "advice": "具体的优化建议文本"
}

V4 Flash 会根据执行计划中的 Extra 信息(如 Using filesort)和 key 为空等特征,推断出需要创建什么索引,有时还会改写成更高效的 SQL 写法(比如将 IN 改为 EXISTS)。

3.5 前端页面:一个 H5 就够了

所有功能通过一个单页的 index.html 暴露,放在 src/main/resources/static/ 下。

用户输入需求,点击按钮,后端返回三个部分:生成的 SQL、EXPLAIN 结果、优化建议和索引 DDL。页面样式简洁,启动 Spring Boot 后直接访问 http://localhost:8080 即可。

四、运行效果演示

启动项目后,访问:

输入中文需求,比如输入:查询近30天每个品类的销售额排行,选择 pro 模型,选择 MySQL,启用优化分析,点击生成 SQL:

可以看到:

  • DeepSeek 理解了我们输入的中文语言并生成了 sql 语句
  • 并且让它执行了 MySQL Explain 并输出了解析结果
  • 通过解析结果给出了优化建议

五、总结

本文利用 DeepSeek V4 的推理能力,构建了一个 "自然语言 → SQL → 执行计划 → 优化建议" 的自动化工具。核心优势:

  • 元数据驱动:让 AI "理解"你的数据库结构,减少幻觉。
  • 闭环验证:基于真实 EXPLAIN,而不是理论分析。
  • 成本可控:生成用 Pro 保证质量,优化用 Flash 降低成本。
  • 开箱即用:H5 页面 + Spring Boot,一键启动。

DeepSeek V4 的 SQL 能力正在推动一种新的开发体验:从"写 SQL"到"描述业务",AI 负责翻译和打磨


项目源码仓库https://github.com/iweidujiang/deepseek-v4-playground ,欢迎广大 coder 关注,star,感谢!

相关推荐
草履虫君4 小时前
若用wsL方式安装openclaw 就不需要安装win原生的node和git
经验分享·git·ai
程序员鱼皮5 小时前
小米送了我 16 亿 tokens,给我测爽了!手把手教你领取 | 附 Claude Code + MiMo-V2.5 实战测评
计算机·ai·程序员·编程·ai编程
秒云5 小时前
MIAOYUN | 每周AI新鲜事儿 260430
人工智能·ai·语言模型·aigc·ai编程
码途漫谈5 小时前
Easy-Vibe开发篇阅读笔记(十二)——后端开发之如何集成Stripe等收费系统
笔记·ai·开源·状态模式·ai编程
java1234_小锋5 小时前
Spring AI 2.0 开发Java Agent智能体 - 新建 HelloWorld 项目
java·人工智能·spring·spring ai
PM老周5 小时前
AI时代项目管理工具体验测评:功能效率协作与研发团队选型
ai·aigc·团队开发·ai编程
暮色念了红尘5 小时前
CC Switch — Ubuntu 20.04 可用版本
ubuntu·ai·rust·ubuntu 20.04·vibe coding·cc swich
大数据在线6 小时前
AI计算新生态:旧地图找不到新大陆
cuda·昇腾·cann·英伟达·deepseek
Irissgwe6 小时前
LangChain之核心组件(消息与提示词模板)
人工智能·ai·langchain·llm·langgraph