TiDB 向量搜索实战:2026年用 TiDB 构建 AI 应用完全指南

分布式数据库

2026年,为什么 TiDB 向量搜索是 AI 应用的游戏规则改变者

传统 AI 应用架构有一个痛点:你需要一个关系型数据库存业务数据,还需要一个向量数据库存 Embedding。两套数据库意味着数据同步、一致性维护、运维成本翻倍。

TiDB 8.0+ 引入的向量搜索功能彻底改变了这个局面——一个数据库同时支持 SQL 和向量搜索。你可以在同一个查询中同时做关系型过滤和语义检索,这就是 HTAP + Vector 的威力。

特性 TiDB Vector Milvus Pinecone Weaviate
SQL 支持 原生 GraphQL
向量搜索 原生 原生 原生 原生
事务支持 ACID 有限 有限
HTAP
部署方式 自托管/云 自托管/云 仅云 自托管/云
混合查询 SQL+Vector 标量过滤 元数据过滤 GraphQL过滤
水平扩展 自动 手动 自动 手动
维度上限 16384 32768 2048 65535
索引类型 HNSW IVF/HNSW 自动 HNSW
开源

TiDB 8.0+ 向量索引配置

安装和连接

# 安装 TiDB Python 客户端
pip install tidb-vector sqlalchemy pymysql

# 或使用 TiDB Serverless(推荐快速开始)
# 获取连接字符串:https://tidbcloud.com

创建带向量列的表

from sqlalchemy import create_engine, Column, Integer, String, Text
from sqlalchemy.orm import declarative_base, Session
from tidb_vector.sqlalchemy import VectorType
import numpy as np

Base = declarative_base()

class Document(Base):
    __tablename__ = "documents"

    id = Column(Integer, primary_key=True)
    content = Column(Text)
    category = Column(String(50))
    source = Column(String(100))
    embedding = Column(VectorType(1536))  # OpenAI ada-002 维度

# 创建引擎和表
engine = create_engine(
    "mysql+pymysql://root:@localhost:4000/testdb",
    echo=True
)
Base.metadata.create_all(engine)

创建向量索引

-- 创建 HNSW 向量索引
CREATE VECTOR INDEX idx_doc_embedding ON documents(embedding)
WITH METRIC = 'cosine', DIMENSION = 1536;

-- 查看索引信息
SHOW CREATE TABLE documents;

-- 向量搜索查询
SELECT id, content, category,
       vec_cosine_distance(embedding, @query_vector) AS distance
FROM documents
WHERE category = 'tech'
ORDER BY distance
LIMIT 10;

完整 Python 实现:插入、搜索、混合查询

插入向量数据

import openai
from sqlalchemy.orm import Session

client = openai.OpenAI(api_key="sk-xxx")

def get_embedding(text: str) -> list[float]:
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

def insert_documents(session: Session, documents: list[dict]):
    for doc in documents:
        embedding = get_embedding(doc["content"])
        document = Document(
            content=doc["content"],
            category=doc["category"],
            source=doc["source"],
            embedding=embedding
        )
        session.add(document)
    session.commit()

# 使用示例
with Session(engine) as session:
    docs = [
        {"content": "TiDB是分布式HTAP数据库,支持OLTP和OLAP", "category": "database", "source": "docs"},
        {"content": "向量搜索通过Embedding实现语义相似度检索", "category": "ai", "source": "docs"},
        {"content": "Kubernetes是容器编排平台,用于微服务部署", "category": "devops", "source": "docs"},
        {"content": "RAG结合检索和生成,提升LLM回答准确性", "category": "ai", "source": "blog"},
    ]
    insert_documents(session, docs)

向量搜索

from tidb_vector.sqlalchemy import vec_cosine_distance

def vector_search(session: Session, query: str, top_k: int = 10):
    query_embedding = get_embedding(query)

    results = session.query(
        Document.id,
        Document.content,
        Document.category,
        Document.source,
        vec_cosine_distance(Document.embedding, query_embedding).label("distance")
    ).order_by("distance").limit(top_k).all()

    return results

# 使用示例
with Session(engine) as session:
    results = vector_search(session, "如何实现语义搜索?")
    for r in results:
        print(f"[{r.category}] {r.content} (distance={r.distance:.4f})")

混合查询:SQL + 向量

这是 TiDB 向量搜索最强大的特性——在同一个查询中结合关系型过滤和语义检索:

def hybrid_search(
    session: Session,
    query: str,
    category: str = None,
    source: str = None,
    top_k: int = 10
):
    query_embedding = get_embedding(query)

    q = session.query(
        Document.id,
        Document.content,
        Document.category,
        Document.source,
        vec_cosine_distance(Document.embedding, query_embedding).label("distance")
    )

    # 关系型过滤 + 向量排序
    if category:
        q = q.filter(Document.category == category)
    if source:
        q = q.filter(Document.source == source)

    results = q.order_by("distance").limit(top_k).all()
    return results

# 在AI类文档中搜索
with Session(engine) as session:
    results = hybrid_search(session, "向量数据库", category="ai")
    for r in results:
        print(f"[{r.category}|{r.source}] {r.content} (distance={r.distance:.4f})")

RAG 应用:用 TiDB 构建检索增强生成

from openai import OpenAI

class TiDBRAG:
    def __init__(self, engine, openai_api_key: str):
        self.engine = engine
        self.llm_client = OpenAI(api_key=openai_api_key)

    def retrieve(self, query: str, top_k: int = 5) -> list[dict]:
        with Session(self.engine) as session:
            results = vector_search(session, query, top_k)
            return [
                {"content": r.content, "category": r.category, "distance": r.distance}
                for r in results
            ]

    def generate(self, query: str, context: list[dict]) -> str:
        context_text = "\n".join([f"[{c['category']}] {c['content']}" for c in context])
        prompt = f"""基于以下参考资料回答问题。如果参考资料中没有相关信息,请说明。

参考资料:
{context_text}

问题:{query}

回答:"""

        response = self.llm_client.chat.completions.create(
            model="gpt-4o",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.1
        )
        return response.choices[0].message.content

    def query(self, question: str, top_k: int = 5) -> str:
        context = self.retrieve(question, top_k)
        answer = self.generate(question, context)
        return answer

# 使用示例
rag = TiDBRAG(engine, openai_api_key="sk-xxx")
answer = rag.query("TiDB的向量搜索和Milvus有什么区别?")
print(answer)

与专用向量数据库对比

Milvus 对比

维度 TiDB Vector Milvus
数据模型 关系型+向量 纯向量
查询语言 SQL SDK/REST
事务 ACID 最终一致
运维复杂度
适用场景 业务+AI混合 纯向量检索

Pinecone 对比

维度 TiDB Vector Pinecone
部署 自托管/云 仅云
成本 低(开源) 按量付费
数据控制 完全 有限
混合查询 SQL+Vector 元数据过滤
扩展 自动 自动

5 个常见陷阱

1. 向量维度不匹配

Embedding 模型输出的维度必须与表定义的维度一致。

# 错误:维度不匹配
# 表定义:VectorType(1536)  → OpenAI ada-002
# 实际使用:text-embedding-3-small → 1536 ✓
# 实际使用:text-embedding-3-large → 3072 ✗ 会报错

# 解决:创建表时指定正确维度
class DocumentLarge(Base):
    __tablename__ = "documents_large"
    id = Column(Integer, primary_key=True)
    content = Column(Text)
    embedding = Column(VectorType(3072))  # 匹配 large 模型

2. 忽略索引创建

没有向量索引时,搜索退化为全表扫描,性能极差。

-- 必须创建向量索引
CREATE VECTOR INDEX idx_embedding ON documents(embedding)
WITH METRIC = 'cosine', DIMENSION = 1536;

-- 验证索引
SHOW INDEX FROM documents;

3. 批量插入未优化

逐条插入效率极低,应使用批量操作。

# 低效:逐条插入
for doc in documents:
    session.add(doc)
    session.commit()  # 每次都提交

# 高效:批量插入
session.bulk_save_objects(documents)
session.commit()

4. 距离度量不一致

插入时和查询时必须使用相同的距离度量(cosine、L2、inner product)。

-- 创建索引时指定 cosine
CREATE VECTOR INDEX idx_emb ON documents(embedding)
WITH METRIC = 'cosine', DIMENSION = 1536;

-- 查询时也必须用 cosine 距离
SELECT *, vec_cosine_distance(embedding, @query) AS dist
FROM documents ORDER BY dist LIMIT 10;

-- 错误:索引用 cosine,查询用 L2
SELECT *, vec_l2_distance(embedding, @query) AS dist  -- ✗ 结果不准确
FROM documents ORDER BY dist LIMIT 10;

5. 连接池未配置

高并发下,默认连接池会导致连接耗尽。

from sqlalchemy import create_engine

engine = create_engine(
    "mysql+pymysql://root:@localhost:4000/testdb",
    pool_size=20,
    max_overflow=10,
    pool_timeout=30,
    pool_recycle=3600,
    pool_pre_ping=True
)

10 个错误排查

# 错误现象 可能原因 排查方法
1 维度不匹配错误 Embedding维度与表定义不一致 检查模型输出维度和VectorType参数
2 搜索结果为空 向量索引未创建 SHOW INDEX FROM documents
3 搜索性能极慢 缺少向量索引 检查HNSW索引是否存在
4 连接超时 连接池耗尽 调整pool_size和max_overflow
5 距离计算异常 度量不一致 确认索引和查询使用同一度量
6 内存溢出 批量插入数据量过大 分批插入,每批1000-5000条
7 精度不够 HNSW参数ef_search太小 增大ef_search值
8 插入失败 向量包含NaN/Inf 插入前检查embedding有效性
9 混合查询慢 关系型过滤未走索引 为过滤列创建B-Tree索引
10 结果排序错误 距离和相似度混淆 cosine距离越小越相似
# 通用调试工具
def debug_vector(embedding: list[float]):
    arr = np.array(embedding)
    print(f"维度: {arr.shape}")
    print(f"范数: {np.linalg.norm(arr):.6f}")
    print(f"包含NaN: {np.any(np.isnan(arr))}")
    print(f"包含Inf: {np.any(np.isinf(arr))}")
    print(f"范围: [{arr.min():.6f}, {arr.max():.6f}]")

性能调优建议

-- HNSW 索引参数调优
CREATE VECTOR INDEX idx_doc_embedding ON documents(embedding)
WITH METRIC = 'cosine', DIMENSION = 1536,
     EF_CONSTRUCTION = 256,  -- 构建时搜索宽度(越大越精确,构建越慢)
     M = 16;                  -- 每层最大连接数(越大越精确,内存越多)

-- 查询时调整 ef_search
SET SESSION tidb_vector_ef_search = 128;  -- 默认64,增大提升精度降低速度
参数 默认值 推荐范围 说明
EF_CONSTRUCTION 64 64-256 构建精度,越大索引质量越高
M 16 12-48 图连接度,越大精度越高内存越多
ef_search 64 64-512 查询精度,越大结果越精确速度越慢

在线工具推荐


总结:TiDB 向量搜索将 SQL 和向量检索统一在一个数据库中,是 2026 年构建 AI 应用的最佳选择之一。它消除了关系型数据库和向量数据库之间的数据同步痛点,支持 ACID 事务 + 语义检索的混合查询。关键实践:确保向量维度匹配、创建 HNSW 索引、使用批量插入、保持度量一致性、配置连接池。对于 RAG 应用,TiDB 的混合查询能力让你可以在语义检索的同时做精确的关系型过滤,这是专用向量数据库难以优雅实现的。

本站提供浏览器本地工具,免注册即可试用 →

#TiDB#向量搜索#向量数据库#语义检索#HTAP#RAG#AI应用#Python