Массовая вставка данных в таблицу mssql с использованием узла mssql

Я использую node-mssql

Мой файл запроса, как показано ниже

BEGIN TRANSACTION
DECLARE @status NVARCHAR(30);
SET @status = 'create';
DECLARE @i UNIQUEIDENTIFIER;
SET @i = NEWID();
DECLARE @t DATETIME2;
SET @t = SYSUTCDATETIME();
IF NOT EXISTS( 
    SELECT * FROM user WHERE email = @email AND company_id= @company_id
) BEGIN
SET @i = NEWID();
INSERT INTO user (comapny_id, id, email, password) VALUES ( @company_id, @i, @email, @password);
INSERT INTO user_transaction( id, date, type) VALUES ( @i, @t, @status);
SELECT @i as 'id', @email as 'email';
END ELSE BEGIN
SELECT NULL as 'id', @email as 'email';
END
COMMIT TRANSACTION

И мой createuserquery в файле query.js

 datastore.getQueryFromSqlFile('create_user', (err: any, query: string) => {
    if (err) {
        done(err);
    } else {
        var request = new sql.Request(connectionOrTransaction);
        request.input('email', sql.NVarChar(200), email);
        request.input('password', sql.NVarChar(200), some_password);
        request.input('company_id', sql.UniqueIdentifier, company_id);
        request.query(query, function (err, data) {});

Теперь мне нужно изменить их, чтобы вставить большую часть пользовательских данных, импортированных из файла CSV (> 20000 записей). Я думал сделать что-то вроде

 async.mapSeries(Object.keys(users), function (item, callback) {
     query.createuser(email, company_id, function (err, data) {
         callback(err, err ? 'Error message: ' + data : data);        
     });
 }, function (err, results) {
 })

Но это неэффективно, так как я получаю тайм-аут соединения. Увеличение connectionTimeout или requestTimeout в конфигурационном файле мало помогает.

Как я могу ускорить свой запрос для массовой вставки около 20000-40000 записей за попытку?


person Sami    schedule 14.10.2014    source источник


Ответы (1)


Для меня это выглядит как работа для подготовленного заявления.

var ps = new sql.PreparedStatement();
ps.input('email', sql.VarChar);
ps.input('password', sql.VarChar);
ps.input('company_id', sql.Int);
ps.prepare(" ... your sql ... ", function(err) {
    // ... error checks

    // users must be an array of users
    async.mapSeries(users, function(user, next) {
        ps.execute({email: user.email, password: user.password, company_id: user.company_id}, next);
    }, function(err) {
        // ... error checks

        ps.unprepare(function(err) {
            // ... error checks

            // done !
        });
    });
});

Каждый execute вызывается как одиночный запрос, поэтому requestTimeout не должно прерываться по тайм-ауту. connectionTimeout - это то, что влияет только на фазу подключения. Как только вы подключитесь к базе данных, значение имеет только requestTimeout.

person Patrik Šimek    schedule 14.10.2014