我试图将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数据中的索引列并按行号选择的情况下拉取和写入块?
跑步:
答案 0 :(得分: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
尝试为您的块找到一个好的大小(当然取决于您的系统),以避免再次遇到内存不足异常。您应该捕获异常,然后根据您的努力,删除已传输的数据或计算较小的块大小(更难一点)并继续其余的传输。