批量数据导入的性能与完整性问题

刚才有网友问了一个技术问题:

我从其他接口 采集一批数据,每次上万条左右,然后存到数据库,存库前还要每条每条的判断数据库存不存在这条数据,不存在才能写库,有没有性能好的实现思路啊?

这是典型的批量数据导入的问题,一般追求是速度。

8年前来澳洲后第一份工作是一个做智能表(水电煤等)的公司,软硬件结合,软件系统采集数十万的智能表的数据,系统里一些表,单个超过30亿条记录,每天更新上千万条记录,为了这个专门实现了一个高度优化的批量导入功能。

现在拿微软SQL Server做例子,说说思路。

首先,要实现速度,会考虑批量导入(Bulk Copy),但一般来源数据格式和目标表达格式不一样(譬如字段数量、类型等),甚至需要做一些计算,甚至要从关联表取数据,所以一般先会导入到临时表,然后再插入目标表。

使用Bulk Copy有一个问题,是它不确保插入数据的顺序,所以如果你必须要求数据插入完全按照来源数据的要求,你必须确保Bulk Copy之前主键字段的值是按顺序的,因为簇集索引是物理顺序,所以会默认按这个排序。

插入目标表需要考虑2个问题:

  1. 唯一性:主键可能会重复,一般采用修改主键索引忽略重复记录,但是这个做法可能会忽略掉后面比较新的数据。
  2. 完整性:如果这个批量导入逻辑可以是多线程/多进程跑的话,那么需要额外的逻辑去处理不会重复操作。

插入数据要确保唯一性又要考虑最新数据会被导入,一般做法是判断目标表是否存在数据,如果不存在则插入,如果存在则更新,这个操作是有重复处理浪费时间,所以可以用SQL Server的MERGE语句,把插入和更新合二为一。

有朋友问:“那是否有更快的办法?”。是有的,那就是支持多线程/多进程。思路如下:

  1. 客户端调用BulkCopy,获得起始、结束Id
  2. 完成调用服务器的存储过程处理这批数据

这样做可以支持并发问题,提高性能。

如何成为爆栈成员:

  • 加我微信 unruledboy ,进入技术群

版权所有

所有文章内容版权所有,任何形式的转发/使用都必须先征得本站书面同意。本站保留一切追究的权利。

发表评论