侧边栏壁纸
博主头像
博主等级

  • 累计撰写 23 篇文章
  • 累计创建 35 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Milvus-表格数据存储设计

前尘一梦
2025-07-02 / 0 评论 / 0 点赞 / 33 阅读 / 41103 字

前言

在企业知识库系统的落地实践中,我们通常需要处理两大类数据:非结构化数据(如文本、图片)和结构化数据(如数据表格)。尽管非结构化数据处理方案已相对成熟,但如何高效存储和检索结构多变的企业表格数据,仍是一个值得深入探讨的技术问题。本文将聚焦于表格数据的存储与检索方案,分享一种基于动态字段映射的设计思路。

数据表格的抽象:从“动态表”到“固定表”

当用户上传一份业务表格(如一份“学生信息表”)时,最直接的存储方案是在数据库中创建一张与之对应的物理表。然而,在实际业务中,用户可能上传来自不同业务、结构各异的表格(如“员工考勤表”、“销售订单表”)。如果为每一份表格都创建一张新表,将导致数据库中存在大量结构迥异的表,难以维护和管理。

为了解决这个问题,我们引入了动态字段映射的设计思想。其核心在于,将用户上传的任意表格,都抽象为一种通用的、可动态扩展的模型,并将其数据存入几张固定的物理表中。具体而言:

  • 总表 (t_file_category):用于记录所有文件(包括非结构化文件和结构化表格)的元信息。

  • 字段表 (t_structured_field):用于定义每个结构化表格拥有哪些字段(即表头)。

  • 字段值表 (t_structured_field_data):以“行-字段”的键值对形式,存储表格中每一个单元格的数据。

通过这种设计,无论用户上传的表格结构如何变化,我们都能将其动态地映射到固定的几张数据库表中,实现了“以不变应万变”。

核心表结构设计

1. 总表 (t_file_category)

总表是所有文件的目录,通过 type字段区分是结构化数据还是非结构化数据。

CREATE TABLE `t_file_category` (
  `id` bigint NOT NULL COMMENT '序列',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件夹名称',
  `code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件夹编码',
  `parent_code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '父文件夹编码',
  `source` int DEFAULT '0' COMMENT '来源',
  `state` int DEFAULT '0' COMMENT '状态',
  `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '说明',
  `label` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '标签',
  `type` int DEFAULT '1' COMMENT '类型(0:结构化,1:非结构化)',
  `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `workspace_id` bigint DEFAULT NULL COMMENT '归属工作空间ID',
  `tenant_id` bigint DEFAULT '0' COMMENT '租户编号',
  `sorting` int DEFAULT '0' COMMENT '排序',
  `version` int DEFAULT '1' COMMENT '版本号',
  `error_msg` json DEFAULT NULL COMMENT '错误信息',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='总表';

2. 字段表 (t_structured_field)

此表定义了每个结构化表格的具体结构(表头)。

CREATE TABLE `t_structured_field` (
  `id` bigint NOT NULL COMMENT '序列',
  `category_id` bigint DEFAULT NULL COMMENT '总表id',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '字段名称',
  `default_value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '默认值',
  `enable_search` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否参与检索',
  `enable_llm` bit(1) NOT NULL DEFAULT b'1' COMMENT '是否参与模型回复',
  `source` int DEFAULT '0' COMMENT '数据来源(0:本地导入,1:后台上传)',
  `state` int DEFAULT '0' COMMENT '状态',
  `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '说明',
  `label` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '标签',
  `type` int DEFAULT '0' COMMENT '类型(0:string,1:double,2:long,3:datetime,4:link)',
  `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `workspace_id` bigint DEFAULT NULL COMMENT '归属工作空间ID',
  `tenant_id` bigint DEFAULT '0' COMMENT '租户编号',
  `sorting` int DEFAULT '0' COMMENT '排序',
  `version` int DEFAULT '1' COMMENT '版本号',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='结构化数据字段表';

3. 字段值表 (t_structured_field_data)

此表以“长链”或“键值对”的形式存储表格中每一个单元格的数据。

CREATE TABLE `t_structured_field_data` (
  `id` bigint NOT NULL COMMENT '序列',
  `category_id` bigint DEFAULT NULL COMMENT '总表id',
  `line_no` bigint DEFAULT NULL COMMENT '行号',
  `field_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '字段id',
  `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '值',
  `source` int DEFAULT '0' COMMENT '数据来源(0:本地导入,1:后台上传)',
  `state` int DEFAULT '0' COMMENT '状态',
  `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '说明',
  `label` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '标签',
  `type` int DEFAULT '0' COMMENT '类型(0:string,1:double,2:long,3:datetime,4:link)',
  `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `workspace_id` bigint DEFAULT NULL COMMENT '归属工作空间ID',
  `tenant_id` bigint DEFAULT '0' COMMENT '租户编号',
  `sorting` int DEFAULT '0' COMMENT '排序',
  `version` int DEFAULT '1' COMMENT '版本号',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_name` (`field_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='结构化数据字段值';

设计示例

假设用户上传了以下“学生信息表”:

姓名

年龄

张三

22

李四

23

在数据库中,它的存储形式将是:

  • t_structured_field(字段定义):

    id

    category_id

    name

    type

    1

    1001

    姓名

    0

    2

    1001

    年龄

    2

  • t_structured_field_data(单元格数据):

    id

    category_id

    line_no

    field_id

    value

    1

    1001

    1

    1

    张三

    2

    1001

    1

    2

    22

    3

    1001

    2

    1

    李四

    4

    1001

    2

    2

    23

4. JSON冗余表 (t_structured_data)

为了前端能快速回显整个表格,我们额外设计了一张冗余表,以JSON格式存储整行数据,这是一种典型的“用空间换时间”的优化策略。

CREATE TABLE `t_structured_data` (
  `id` bigint NOT NULL COMMENT '序列',
  `content` json DEFAULT NULL COMMENT '内容',
  `category_id` bigint DEFAULT NULL COMMENT '总表id',
  `source` int DEFAULT '0' COMMENT '数据来源(0:本地导入,1:后台上传)',
  `state` int DEFAULT '0' COMMENT '状态',
  `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '说明',
  `label` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '标签',
  `type` int DEFAULT '1' COMMENT '类型',
  `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除',
  `workspace_id` bigint DEFAULT NULL COMMENT '归属工作空间ID',
  `tenant_id` bigint DEFAULT '0' COMMENT '租户编号',
  `sorting` int DEFAULT '0' COMMENT '排序',
  `version` int DEFAULT '1' COMMENT '版本号',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_categoryid` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='结构化数据内容';

向量库表设计

在向量检索场景中,我们需要将上述结构化数据转换为向量进行存储。这里面临一个关键决策:是存储所有字段的向量,还是只存储需要被检索的字段的向量?

方案一:存储所有字段数据

  • 优点:灵活性高。可以随时通过调整配置,选择不同的字段组合作为检索目标,无需重新处理和数据回填。

  • 缺点:存储成本较高,向量维度可能较大。

方案二:仅存储索引字段数据

  • 优点:按需存储,存储成本和计算效率更优。

  • 缺点:灵活性差。一旦表格向量化完成,检索字段即被固定,若想变更则需重新处理整个表格数据,成本高昂。

决策建议:

  • 如果业务需求多变,需要频繁调整检索字段,方案一更合适。

  • 如果业务场景稳定,检索目标明确,方案二是更经济高效的选择。

表结构上,还是基于业务表的动态字段映射思想

向量存储表

总结

通过动态字段映射的设计,我们成功地用一套固定的数据库Schema支撑了任意结构的企业表格数据存储。这种方案在灵活性、可维护性和扩展性之间取得了良好的平衡,是企业级知识库处理海量异构表格数据的一种有效实践

0

评论区