Как я могу ускорить обновление большого количества строк - PullRequest
1 голос
/ 18 января 2011

У меня есть таблица, которая имеет 1.400.000 записей.Это простой список документов

Таблица - Документ

  • ID int
  • DocumentPath nvarchar
  • DocumentValid bit

Я сканирую каталог и устанавливаю любой документ, найденный в каталоге, как действительный.

    public void SetReportsToValidated(List<int> validatedReports)
    {
        SqlConnection myCon = null;

        try
        {
            myCon = new SqlConnection(_conn);
            myCon.Open();

            foreach (int id in validatedReports)
            {                    
                SqlDataAdapter myAdap = new SqlDataAdapter("update_DocumentValidated", myCon);
                myAdap.SelectCommand.CommandType = CommandType.StoredProcedure;

                SqlParameter pId = new SqlParameter("@Id", SqlDbType.Int);
                pId.Value = id;
                myAdap.SelectCommand.Parameters.Add(pId); 

                myAdap.SelectCommand.ExecuteNonQuery();
            }
        }
        catch (SystemException ex)
        {
            _log.Error(ex);
            throw;
        }
        finally
        {
            if (myCon != null)
            {
                myCon.Close();
            }
        }
    }

Производительность обновлений в порядке, но я хочу больше.Обновление 1000000 документов на действительные занимает более 1 часа.Есть ли хороший способ ускорить обновления?Я думаю об использовании какой-то партии (например, табличных параметров).Каждое обновление занимает около 5-10 мс при профилировании на SQLServer.

Ответы [ 3 ]

2 голосов
/ 18 января 2011

В данный момент вы вызываете БД для каждой записи в отдельности.Вы можете использовать SqlDataAdapter для выполнения массовых обновлений путем (в очень кратких словах):

1) определения одного SqlDataAdapter2) установите .UpdateCommand на адаптере для вашего обновления sproc3) вызовите метод .Update на адаптере, передав ему DataTable, содержащий идентификаторы документов, подлежащих обновлению.Это объединит обновленные строки из DataTable в БД, вызывая sproc для каждой записи в пакетном режиме.Вы можете контролировать размер пакета через свойство .BatchSize.4) То, что вы делаете, это удаление ручного, построчного цикла, что неэффективно для пакетных обновлений.

См. Примеры:http://support.microsoft.com/kb/308055http://www.c -sharpcorner.com / UploadFile / 61b832 / 4430 / В качестве альтернативы вы можете:1) Используйте SqlBulkCopy для массовой вставки всех идентификаторов в новую таблицу в базе данных (очень эффективно)2) После загрузки в эту промежуточную таблицу выполните один оператор SQL, чтобы обновить основную таблицу из этой промежуточной таблицы для проверки документов.

См. Примеры:http://www.adathedev.co.uk/2010/02/sqlbulkcopy-bulk-load-to-sql-server.htmlhttp://www.adathedev.co.uk/2011/01/sqlbulkcopy-to-sql-server-in-parallel.html

2 голосов
/ 18 января 2011

Прочитайте отчеты и добавьте их вместе в DataTable (поскольку они имеют одинаковые измерения), затем используйте объект SqlBulkCopy для загрузки всего объекта. Вероятно, будет работать лучше для вас. Я не думаю, что у вас будут проблемы с памятью, учитывая небольшое количество столбцов и строк.

0 голосов
/ 18 января 2011

Вместо создания адаптера и параметра каждый раз в цикле, просто создайте их один раз и присвойте параметру другое значение:

            SqlDataAdapter myAdap = new SqlDataAdapter("update_DocumentValidated", myCon);
            myAdap.SelectCommand.CommandType = CommandType.StoredProcedure;

            SqlParameter pId = new SqlParameter("@Id", SqlDbType.Int);
            myAdap.SelectCommand.Parameters.Add(pId); 

            foreach (int id in validatedReports)
            {
                myAdap.SelectCommand.Parameters[0].Value = id;  
                myAdap.SelectCommand.ExecuteNonQuery();
            }

Это может не привести к значительному улучшению, но лучше по сравнению с исходным кодом. Кроме того, поскольку вы вручную выполняете объект SqlCommand, вам совсем не нужен адаптер. Просто используйте SqlCommand напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...