当MySQL遇见AI:使用Vector扩展实现智能语义搜索

简介: 传统数据库的关键词搜索已无法满足现代应用对智能语义查询的需求。本文介绍如何通过MySQL的向量扩展(Vector Extension),将大模型产生的文本嵌入向量存储在MySQL中,并实现高效的语义相似度搜索。我们将完整演示从环境准备、数据库表设计、Java应用集成到性能优化的全流程,让您的传统关系型数据库瞬间具备AI智能检索能力,为构建下一代智能应用提供核心数据支撑。

一、 引言:超越LIKE的智能搜索
在知识库、电商平台、内容推荐等场景中,用户往往无法用精确的关键词描述需求。例如,用户可能搜索“适合雨天听的舒缓音乐”,而非简单的“轻音乐”。传统的LIKE或全文索引基于词法匹配,难以理解这种语义意图。

解决方案是文本嵌入向量。大模型可以将文本转换为高维空间中的向量(一组浮点数),语义相似的文本其向量在空间中的距离也更近。通过计算向量距离(如余弦相似度),就能实现“意思上”的搜索。

近年来,主流数据库纷纷增加对向量类型的原生支持。MySQL 8.0.31及以上版本通过VECTOR数据类型和相应的距离函数,使开发者能在熟悉的MySQL生态中直接进行向量运算,无需引入额外的向量数据库,极大简化了技术架构。

二、 环境准备与数据库配置

  1. 前提条件

MySQL Server版本 >= 8.0.31

确认已安装MySQL Vector扩展(通常是默认包含的)

Java 17及以上

Spring Boot 3.x

  1. 创建支持向量的数据库表

我们以products产品表为例,为其增加语义搜索能力。

sql
-- 创建数据库
CREATE DATABASE ai_shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE ai_shop;

-- 创建产品表,并新增向量字段
CREATE TABLE products (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL COMMENT '产品名称',
description TEXT COMMENT '产品描述',
-- 新的向量字段:用于存储description的文本嵌入向量
-- 1536维度适配OpenAI的text-embedding-3-small模型
description_vector VECTOR(1536) NOT NULL,
-- 为向量字段创建索引以加速搜索
INDEX description_vector_idx (description_vector) USING VECTOR
) COMMENT='产品表(带向量搜索)';

-- 创建一个函数来简化余弦相似度计算
CREATE FUNCTION cosine_similarity(a VECTOR, b VECTOR) RETURNS FLOAT
DETERMINISTIC
RETURN COSINE_SIMILARITY(a, b);
关键点说明:

VECTOR(1536):定义了一个1536维的向量字段,维度需与所选嵌入模型匹配。

USING VECTOR:指定为该向量字段创建专门的向量索引。

COSINE_SIMILARITY:MySQL内置的余弦相似度计算函数,值越接近1,相似度越高。

三、 Java应用集成

  1. 项目依赖(pom.xml)

除了Spring Boot基础依赖,我们还需要MySQL驱动、JDBC以及OpenAI客户端。

xml



org.springframework.boot
spring-boot-starter-data-jdbc


com.mysql
mysql-connector-j
runtime



dev.langchain4j
langchain4j
0.29.0


dev.langchain4j
langchain4j-open-ai
0.29.0

  1. 应用配置(application.yml)

yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/ai_shop?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: your_username
password: your_password

openai:
api-key: ${OPENAI_API_KEY}
embedding-model: text-embedding-3-small

  1. 核心实体与Repository

定义与数据库表映射的实体类。这里我们使用Spring Data JDBC,因其对自定义类型映射更为灵活。

java
// Product.java - 实体类
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

@Table("products")
public class Product {
@Id
private Long id;
private String name;
private String description;

// 重点:向量字段的映射
// MySQL JDBC驱动会将float数组与VECTOR类型自动转换
@Column("description_vector")
private float[] descriptionVector;

// 构造器、Getter和Setter省略...

}
java
// ProductRepository.java - 数据访问层
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;

public interface ProductRepository extends CrudRepository {

/**
 * 核心语义搜索查询
 * 使用余弦相似度,并按相似度得分从高到低排序
 * :queryVector 是由用户查询文本通过AI模型转换而来的向量
 */
@Query("""
    SELECT id, name, description, description_vector,
           cosine_similarity(description_vector, :queryVector) AS similarity_score
    FROM products
    WHERE cosine_similarity(description_vector, :queryVector) > :minScore
    ORDER BY similarity_score DESC
    LIMIT :limit
    """)
List<SearchResult> semanticSearch(@Param("queryVector") float[] queryVector,
                                  @Param("minScore") double minScore,
                                  @Param("limit") int limit);

// 定义一个接口来接收包含相似度得分的查询结果
interface SearchResult {
    Long getId();
    String getName();
    String getDescription();
    double getSimilarityScore(); // 计算得到的相似度得分
}

}

  1. 语义搜索服务

该服务负责将用户查询文本转换为向量,并调用Repository进行搜索。

java
// SemanticSearchService.java
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class SemanticSearchService {

private final ProductRepository productRepository;
private final EmbeddingModel embeddingModel; // 文本嵌入模型

public SemanticSearchService(ProductRepository productRepository) {
    this.productRepository = productRepository;
    // 初始化嵌入模型(例如OpenAI)
    this.embeddingModel = OpenAiEmbeddingModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("text-embedding-3-small")
            .build();
}

/**
 * 执行语义搜索
 * @param query 用户查询文本(如:“想要一个续航久的蓝牙耳机”)
 * @param minScore 相似度阈值(0到1之间,如0.75)
 * @param limit 返回结果数量
 * @return 按相似度排序的产品列表
 */
public List<ProductRepository.SearchResult> search(String query, double minScore, int limit) {
    // 1. 将查询文本转换为向量
    float[] queryVector = convertTextToVector(query);

    // 2. 执行向量相似度搜索
    return productRepository.semanticSearch(queryVector, minScore, limit);
}

private float[] convertTextToVector(String text) {
    // 使用EmbeddingModel获取文本的向量表示
    dev.langchain4j.data.embedding.Embedding embedding = embeddingModel.embed(text).content();
    // 将Embedding对象转换为float数组
    // 注意:LangChain4j的Embedding内部是float数组,但需确认维度匹配
    return embedding.vector();
}

/**
 * 添加新产品时,自动为其描述生成向量并存储
 */
public void addProduct(Product product) {
    float[] vector = convertTextToVector(product.getDescription());
    product.setDescriptionVector(vector);
    productRepository.save(product);
}

}

  1. REST控制器

java
// SearchController.java
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/search")
public class SearchController {

private final SemanticSearchService searchService;

public SearchController(SemanticSearchService searchService) {
    this.searchService = searchService;
}

@PostMapping("/semantic")
public List<ProductRepository.SearchResult> semanticSearch(@RequestBody SearchRequest request) {
    return searchService.search(request.query(), 0.7, 10); // 阈值0.7,返回10条
}

@PostMapping("/product")
public Product addProduct(@RequestBody Product product) {
    searchService.addProduct(product);
    return product;
}

public record SearchRequest(String query) {}

}
四、 测试与性能优化

  1. 测试流程

向/api/search/product POST一个产品:{"name": "无线蓝牙耳机", "description": "这款耳机拥有超长续航30小时,音质纯净,佩戴舒适,适合运动和通勤。"}

向/api/search/semantic POST一个查询:{"query": "有没有能长时间使用不用充电的耳机推荐?"}

观察返回结果,即使没有完全匹配的关键词,也能凭借语义相似度找到正确产品。

  1. 性能优化建议

索引优化:确保description_vector字段上已创建向量索引。

维度选择:在精度和性能间权衡。OpenAI的text-embedding-3-small模型(1536维)在性能和效果上是不错的选择。

分区与分片:对于海量数据,可考虑按业务分区或使用MySQL分片来减少单次搜索的数据量。

近似最近邻搜索:对于亿级数据,精确的近邻搜索成本高。可关注未来MySQL对HNSW等近似算法的支持。

五、 总结
通过MySQL的Vector扩展,我们成功地将AI驱动的语义搜索能力无缝集成到了最经典的关系型数据库和Java应用栈中。这种方案的优势在于:

架构简化:无需引入和维护独立的向量数据库,降低系统复杂度。

事务一致性:向量数据和业务数据在同一数据库事务中保持一致。

技术栈统一:Java开发者可以使用熟悉的JDBC/MyBatis/Spring Data等工具进行操作。

随着数据库对AI原生支持能力的不断加强,将向量计算下推到数据层已成为明显趋势。这为Java应用处理非结构化数据、构建更智能的搜索和推荐系统开辟了新的可能性。

目录
相关文章
|
10天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1211 5
|
9天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1176 87
|
10天前
|
云栖大会
阿里云云栖大会2025年9月24日开启,免费申请大会门票,速度领取~
2025云栖大会将于9月24-26日举行,官网免费预约畅享票,审核后短信通知,持证件入场
1771 12
|
19天前
|
人工智能 运维 安全
|
2天前
|
资源调度
除了nrm-pm,还有哪些工具可以管理多个包管理器的源?
除了nrm-pm,还有哪些工具可以管理多个包管理器的源?
230 127
|
10天前
|
弹性计算 Kubernetes jenkins
如何在 ECS/EKS 集群中有效使用 Jenkins
本文探讨了如何将 Jenkins 与 AWS ECS 和 EKS 集群集成,以构建高效、灵活且具备自动扩缩容能力的 CI/CD 流水线,提升软件交付效率并优化资源成本。
362 0

热门文章

最新文章