【问题标题】:Streaming over 1m records from SQL Server to MongoDB using Node.js使用 Node.js 将超过 100 万条记录从 SQL Server 流式传输到 MongoDB
【发布时间】:2016-09-17 23:57:25
【问题描述】:

我正在尝试将 8,000,000 行数据从 Microsoft SQL Sever 复制到 MongoDB。它适用于 100,000 条记录,但是当我尝试提取 1,000,000 条记录(或全部)时,我收到以下错误:

致命错误:CALL_AND_RETRY_LAST 分配失败 - 进程内存不足

这是我目前正在使用的代码(Coffeescript):

MsSqlClient   = require 'mssql'
MongoClient = require('mongodb').MongoClient

config = {}
config.mongodb = 'mongodb://localhost:27017/dbname'
config.mssql = 'mssql://user::pass@host/dbname'

Promise.all(
  [
    MongoClient.connect config.mongodb
    MsSqlClient.connect config.mssql
  ]
).then (a) ->
  mongo = a[0]
  sql = a[1]

  collection = mongo.collection "collection_name"

  request = new MsSqlClient.Request()
  request.stream = true

  request.on 'row', (row) ->
    collection.insert(row)

  request.on 'done', (affected) ->
    console.log "Completed"

  sql.on 'error', (err) ->
    console.log err

  console.log "Querying"
  request.query("SELECT * FROM big_table")

.catch (err) ->
  console.log "ERROR: ", err

似乎写入 MongoDB 的时间比从 SQL Server 下载的时间要长,我认为这会导致瓶颈。有没有办法减慢(暂停/恢复)来自 SQL Server 的流,这样我就可以分块提取和写入,而无需在 SQL 数据中添加索引列并按行号选择?

跑步:

  • Windows 7、SQL Server 2012 (SP1)、MongoDB 2.8.0
  • Node.js 4.2.4 / mssql 3.3.0 / mongodb 2.1.19

【问题讨论】:

  • Process out of memory 不是时间问题。显然,您一次性传输的大量数据令人窒息。分批做。
  • 批量处理最好的方法是什么?这就是为什么我询问暂停流(例如,每 1000 行)并在将 1000 条记录写入 mongo 后恢复。或者我应该向 SQL 表添加一个数字索引并一次按索引号 1000 提取行?(SELECT * FROM big_table WHERE id BETWEEN 1000 和 2000)

标签: sql-server node.js mongodb sql-server-2012 streaming


【解决方案1】:

您可以分块进行(例如 50'000)。这是一种方法(仅限 SQL 端)如何做到这一点(不是超快但应该可以):

首先获取块,这些数字必须在 SQL 之外循环:

    -- get blocks

    select count(*) / 50000 as NumberOfBlocksToLoop
    from YOUR.TABLE

获取块,其中 ColumnU 是允许您对表进行排序的列(或者,您可以直接使用 ID,但如果从表中删除数据,您可能会遇到间隙问题):

    -- get first n-block

    declare @BlockNumber int

    set @BlockNumber = 1

    select ColumnX
    from
    (
        select row_number() over (order by ColumnU asc) as RowNumber,
        TABLE.ColumnX
        from YOUR.TABLE
    ) Data
    where RowNumber between ((@BlockNumber - 1) * 50000) + 1 and @BlockNumber * 50000

尝试为您的块找到合适的大小(当然取决于您的系统)以避免再次遇到内存不足异常。您应该捕获异常,然后根据您的努力,要么删除已传输的数据,要么计算更小的块大小(有点困难),然后继续传输其余数据。

【讨论】:

    猜你喜欢
    • 2021-11-27
    • 1970-01-01
    • 2015-03-21
    • 2017-12-23
    • 2012-06-18
    • 2021-12-30
    • 1970-01-01
    • 2012-06-14
    • 2015-04-28
    相关资源
    最近更新 更多