如果只需要一小块,别拉取整个 dump

发布: (2026年1月12日 GMT+8 01:46)
5 min read
原文: Dev.to

Source: Dev.to

问题:为一个小测试准备巨大的备份

在最近的项目中,我需要从分布式数据系统生成复杂的 PDF 报表。
报表依赖 三张表,每张表都有 数百万行

仅为调试单个报表模块而把完整备份(数百 GB)拉到本地机器,既浪费时间又占用磁盘空间。

朴素的做法

大多数团队会从以下选项中选一个:

  • 在本地恢复完整的数据库备份
  • SSMS → 生成脚本(模式 + 数据),针对所需的表。

在大规模时这两种方式都会失效:

完整备份

  • 下载和恢复需要数小时。
  • 占用巨大的磁盘空间。
  • 包含了你不需要的数据。

SSMS “生成脚本”

  • 试图生成庞大的 INSERT 脚本。
  • 常常卡死或内存耗尽。
  • 即使生成成功,执行也可能需要数小时。

到某个时候会变得很清楚:我们不需要整座山,只要一块岩石

更好的办法:使用 BCP 进行精准抽取

对于 SQL Server,首选工具是 bcp(Bulk Copy Program)。
与其搬运整个 200 + GB 的数据库,不如只抽取 调试所需的数据片段 并在本地重新创建。

为什么 BCP 在这种场景下胜过 SSMS

优势说明
速度使用本机二进制流——没有巨大的 INSERT 语句。数百万行可以在几分钟内导出/导入。
稳定性控制台工具不会在繁重的 UI 操作上卡死;要么快速完成,要么给出明确错误。
灵活性既可以导出整张表 也可以 导出任意 SELECT 的结果(包括联接和过滤),从而可以:
‑ 只导出你需要的子集。
‑ 在查询中直接排除或掩码敏感列。

实践工作流:从生产片段到本地调试

  1. 在本地准备模式——执行迁移或运行 DDL 脚本,创建相同的表(仅结构)。

  2. 从上游环境导出数据片段

    bcp "SELECT c.Id, c.Name, o.Id, o.Date, o.Total
         FROM dbo.Customers c
         JOIN dbo.Orders o ON o.CustomerId = c.Id
         WHERE o.Date >= '2025-01-01'"
         queryout orders_customers.dat -n -S your-server -T
    • queryout 导出 SELECT 的结果。
    • -n 使用本机(二进制)格式——快速且紧凑。
    • -T 使用受信任的连接(如有需要可改为 -U/-P)。
  3. 导入到本地数据库

    bcp dbo.OrdersCustomers in orders_customers.dat -n -S localhost -T

    如果你的本地模式更适合,也可以把导出拆成多个文件(每张表一个)。

  4. 使用真实规模进行调试——本地数据库现在拥有相关表、正确的数据结构以及真实的行数(如需可达数百万),而无需恢复完整备份。

何时考虑这种做法

  • 你在上层环境拥有 巨大的 SQL Server 数据库
  • 需要 真实的数据 来调试复杂业务逻辑、复现仅在生产环境出现的 bug,或测试报表/批处理性能。
  • 想避免搬运完整备份、依赖脆弱的 UI 导出,或维护庞大的手工测试数据脚本。

BCP 不是万能钥匙,但当你:

  • 明确知道需要哪一部分数据,
  • 面对的体量对 SSMS 脚本来说太大,且
  • 已经有模式迁移方案,

它可以为你每周节省大量时间,让本地调试更加舒适。

你是如何从大型上游环境为本地数据库提供种子数据的?完整备份、BACPAC、定制种子程序,还是其他方式?

Back to Blog

相关文章

阅读更多 »

数据库事务泄漏

介绍 我们经常谈论 memory leaks,但在 backend development 中还有另一个沉默的性能杀手:Database Transaction Leaks。我最近…

2025 年 SQL Server 客户端比较

概述 如果您使用 SQL Server,客户端工具很重要。它决定了您编写查询、检查数据和管理更改的方式。大多数 SQL Server 客户端共享…