← 返回题目列表

大文本和文件在数据库中如何设计?为什么不建议直接存大文件?

高频 中等 第 2 / 33 题 更新于 2026/07/29
数据库设计大字段文件存储BLOB

简化版

大文件通常不建议直接存数据库 BLOB,而是存对象存储或文件系统,数据库只保存文件元数据和访问地址。大文本要看访问模式:频繁查询的摘要字段列化,正文可单独拆表;避免大字段拖慢列表查询、索引和备份。

详细版

数据库适合管理结构化数据和事务关系,不适合承载大量文件内容。文件、图片、视频常用对象存储,数据库保存 file_idurlsizehashcontent_typecreated_at 等元数据。

大文本字段如文章正文、商品详情、日志内容,可以考虑:

  • 列表页只放摘要,不查正文。
  • 正文拆到详情表。
  • 文件内容放对象存储。
  • 保存 hash 用于去重和完整性校验。
  • 控制大字段不要进入高频索引和热查询路径。

面试重点是:数据库保存元数据,文件内容交给更适合的存储系统。

完整版教学

一、大字段问题不只是占空间

很多人觉得 BLOB 或 TEXT 只是字段大一点,但它会影响查询、缓存、备份、网络传输和页面性能。列表页本来只需要标题,却把几 MB 的正文或图片一起查出来,整个链路都会变慢。

数据库 Buffer Pool 或缓存页被大字段占用后,真正高频的小字段命中率可能下降。备份和复制也会因为大字段变重。

记忆钩子:大字段会拖慢的不只是存储,还有查询路径、缓存、备份和复制。

二、文件内容通常放对象存储

图片、PDF、视频、附件这类文件更适合放对象存储或文件系统,数据库保存元数据。

create table file_meta (
  id bigint primary key,
  storage_key varchar(256) not null,
  file_name varchar(256) not null,
  content_type varchar(128) not null,
  size_bytes bigint not null,
  sha256 varchar(64) not null,
  created_at timestamp not null
);

这样数据库负责事务、权限和检索,文件系统或对象存储负责大对象读写、CDN 分发和生命周期管理。两者各做擅长的事。

三、大文本可以拆冷热字段

文章、商品详情、协议内容这类大文本,有时仍然适合放数据库,但要避免进入高频列表查询。可以把主表和正文表拆开。

article(id, title, summary, status, created_at)
article_body(article_id, content)

列表页查 article,详情页再查 article_body。如果正文平均 50KB,列表一次查 20 条,不拆表可能额外传输约 1MB 内容,而这些内容列表页根本不用。

拆表的目的不是追求形式,而是把热字段和冷字段分开,让高频路径更轻。

四、数据库存 BLOB 不是绝对禁止

有些场景可以把文件存数据库,比如小文件、强事务一致性、内网管理系统、部署环境不方便引入对象存储。但要知道代价。

方案优点代价
数据库存 BLOB事务一致,备份统一表膨胀,复制和备份变重
对象存储扩展好,适合 CDN要处理元数据和文件一致性
文件系统简单直观分布式和备份治理较麻烦

面试里不要绝对说“不能存”,而要说“大多数互联网业务不建议直接存大文件,除非有明确事务或运维理由”。

五、元数据和文件内容的一致性要处理

文件放对象存储后,会出现数据库记录和文件内容不一致的问题。比如文件上传成功但数据库插入失败,或者数据库记录已删除但对象存储文件没删。

常见流程:

上传临时文件 -> 写数据库元数据 -> 标记文件正式可用
删除记录 -> 标记文件待删除 -> 异步清理对象存储
定时任务 -> 扫描孤儿文件和失效记录

不要在事务里直接依赖外部对象存储的强一致回滚。更稳的是用状态字段、异步清理和定期对账。

六、hash、大小和类型字段很重要

文件元数据里 size_bytescontent_typesha256 很实用。大小用于限制上传和展示;类型用于安全校验和响应头;hash 可用于去重、完整性校验和秒传。

同一个 sha256 + size_bytes -> 可能是同一文件
content_type=image/png -> 展示和下载策略
size_bytes=5242880 -> 5MB,便于限额统计

安全上不能只信客户端传来的文件名和 MIME 类型,服务端应做校验,避免上传可执行脚本或伪造类型。

七、常见误区与追问

  • 误区:BLOB 在数据库里,所以一定更安全。 安全取决于权限、访问控制和审计,不是只看存在哪里。
  • 误区:大文本和普通字段放一起没影响。 高频列表查询会被大字段拖慢,缓存和网络传输都会受影响。
  • 误区:文件放对象存储就不需要数据库记录。 仍然需要元数据、权限、归属关系和生命周期状态。
  • 追问:数据库记录和文件不一致怎么办? 用临时状态、异步清理、定时对账处理孤儿文件和失效记录。
  • 追问:文章正文要不要拆表? 如果正文大且列表页高频不需要正文,拆表能减少热查询负担。
  • 追问:hash 字段有什么用? 用于去重、秒传、完整性校验和排查文件是否被篡改。

八、面试中可以这样落地

如果设计附件系统,可以说文件内容放对象存储,数据库保存文件元数据、业务归属和权限信息。上传时先临时态,业务确认后改为正式态。

create table biz_file (
  id bigint primary key,
  biz_type varchar(64) not null,
  biz_id bigint not null,
  storage_key varchar(256) not null,
  size_bytes bigint not null,
  sha256 varchar(64) not null,
  status varchar(32) not null,
  created_at timestamp not null
);

如果是文章正文,则主表放标题摘要,正文表单独存,列表页不查正文。这样回答能同时覆盖性能和一致性。

九、加强记忆

大文本和文件设计记住“内容外置、元数据入库、热冷拆分、一致性对账”。数据库擅长结构化关系和事务,不擅长大量文件传输;对象存储擅长大对象和分发。面试时不要绝对化,而要根据文件大小、访问频率和事务要求解释取舍。