Как сделать пакетное обновление? - PullRequest
6 голосов
/ 21 мая 2010

Мне интересно, есть ли способ сделать пакетное обновление? Я использую MS SQL Server 2005.

Я проверил с sqlDataAdaptor, но кажется, что сначала нужно с ним выбрать оператор select, затем заполнить некоторый набор данных и внести изменения в набор данных.

Теперь я использую linq to sql для выбора, поэтому я хочу попытаться сохранить его таким образом. Однако это слишком медленно, чтобы делать массовые обновления. Так что, я могу оставить свой linq to sql (для выбранной части), но с помощью чего-то другого, чтобы выполнить массовое обновление?

Спасибо

Редактировать

Мне интересен этот способ подготовки таблицы, но я не уверен, как это сделать, и до сих пор не ясно, как это будет быстрее, поскольку я не понимаю, как работает часть обновления.

Так может кто-нибудь показать мне, как это будет работать и как работать с параллельными соединениями?

Edit2

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

using (TestDataContext db = new TestDataContext())
            {
                UserTable[] testRecords = new UserTable[2];
                for (int count = 0; count < 2; count++)
                {
                    UserTable testRecord = new UserTable();

                    if (count == 1)
                    {
                        testRecord.CreateDate = new DateTime(2050, 5, 10);
                        testRecord.AnotherField = true;
                    }
                    else
                    {
                        testRecord.CreateDate = new DateTime(2015, 5, 10);
                        testRecord.AnotherField = false;
                    }


                    testRecords[count] = testRecord;
                }

                StringBuilder sBuilder = new StringBuilder();
                System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder);
                XmlSerializer serializer = new XmlSerializer(typeof(UserTable[]));
                serializer.Serialize(sWriter, testRecords);             

                using (SqlConnection con = new SqlConnection(connectionString))
                {
                    string sprocName = "spTEST_UpdateTEST_TEST";

                    using (SqlCommand cmd = new SqlCommand(sprocName, con))
                    {
                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.CommandType = System.Data.CommandType.StoredProcedure;

                        SqlParameter param1 = new SqlParameter("@UpdatedProdData", SqlDbType.VarChar, int.MaxValue);
                        param1.Value = sBuilder.Remove(0, 41).ToString();
                        cmd.Parameters.Add(param1);
                        con.Open();
                        int result = cmd.ExecuteNonQuery();
                        con.Close();
                    }
                }
            }

@ Фредрик Йоханссон Я не уверен, что ваше высказывание сработает. Как мне кажется, вы хотите, чтобы я сделал заявление об обновлении для каждой записи. Я не могу этого сделать, так как мне нужно будет обновить от 1 до 50 000 записей, и я не буду знать до этого момента.

Редактировать 3

Так что теперь это мой SP. Я думаю, что это должно быть в состоянии делать параллельные соединения, но я хотел убедиться.

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_MassUpdate]
@BatchNumber uniqueidentifier 
AS
BEGIN
    update Product
    set ProductQty = 50
    from Product prod
    join StagingTbl stage on prod.ProductId = stage.ProductId
    where stage.BatchNumber = @BatchNumber

    DELETE FROM StagingTbl
    WHERE BatchNumber = @BatchNumber

END

Ответы [ 5 ]

2 голосов
/ 31 мая 2010

Вы можете использовать sqlDataAdapter для пакетного обновления.Неважно, как вы заполняете свой набор данных.L2SQL или что-то еще, вы можете использовать различные методы для обновления.Просто определите запрос для запуска, используя данные в вашей таблице данных.

Ключом здесь является UpdateBatchSize.Dataadapter будет отправлять обновления в пакетах любого размера, который вы определяете.Вы должны истечь с этим значением, чтобы увидеть, какое число работает лучше всего, но типичные числа 500-1000 работают лучше всего.Затем SQL может оптимизировать обновление и выполнить его немного быстрее.Обратите внимание, что при выполнении пакетных обновлений вы не можете обновить источник строки таблицы данных.

Я использую этот метод для обновления 10-100 КБ, и обычно он выполняется менее чем за 2 минуты.Это будет зависеть от того, что вы обновляете.

Извините, это в VB….

Using da As New SqlDataAdapter
      da.UpdateCommand = conn.CreateCommand
      da.UpdateCommand.CommandTimeout = 300

      da.AcceptChangesDuringUpdate = False
      da.ContinueUpdateOnError = False
      da.UpdateBatchSize = 1000 ‘Expirement for best preformance
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None 'Needed if UpdateBatchSize > 1
      sql = "UPDATE YourTable"
      sql += " SET YourField = @YourField"
      sql += " WHERE ID = @ID"
      da.UpdateCommand.CommandText = sql
      da.UpdateCommand.UpdatedRowSource = UpdateRowSource.None
      da.UpdateCommand.Parameters.Clear()
      da.UpdateCommand.Parameters.Add("@YourField", SqlDbType.SmallDateTime).SourceColumn = "YourField"
      da.UpdateCommand.Parameters.Add("@ID", SqlDbType.SmallDateTime).SourceColumn = "ID"

      da.Update(ds.Tables("YourTable”)
End Using

Другой вариант - скопировать в временную таблицу, а затем запустить запрос на обновление.основной стол из него.Это может быть быстрее.

1 голос
/ 01 июня 2010

Как сказал все анонимный пользователь, используйте SqlBulkCopy, который очень быстр (я обнаружил, что улучшения скорости более чем в 200 раз - с 1500 секунд до 6 секунд). Однако вы можете использовать классы DataTable и DataRows для предоставления данных в SQlBulkCopy (что кажется проще). Использование SqlBulkCopy таким способом имеет дополнительное преимущество, связанное с совместимостью bein .NET 3.0 (Linq был добавлен только в версии 3.5).
Оформить заказ http://msdn.microsoft.com/en-us/library/ex21zs8x%28v=VS.100%29.aspx для примера кода.

1 голос
/ 21 мая 2010

Используйте SqlBulkCopy, который молниеносен. Вам понадобится пользовательская реализация IDataReader, которая перечисляет результаты вашего запроса linq. Посмотрите на http://code.msdn.microsoft.com/LinqEntityDataReader для получения дополнительной информации и некоторого потенциально подходящего кода IDataReader.

0 голосов
/ 25 апреля 2012

Вы можете использовать SqlDataAdapter для пакетного обновления, даже если таблица данных заполняется вручную / программно (из linq любого другого источника).

Только не забудьте вручную установить RowState для строк в таблице данных. Для этого используйте dataRow.SetModified().

0 голосов
/ 21 мая 2010

Вы должны работать с деревьями выражений напрямую, но это выполнимо.Фактически, это уже сделано для вас, вам просто нужно скачать исходный код:

Пакетное обновление и удаление с LINQ to SQL

Альтернативой является просто использоватьхранимые процедуры или специальные SQL-запросы с использованием методов ExecuteMethodCall и ExecuteCommand из DataContext.

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