2012-01-06 3 views
3

В настоящее время мы разрабатываем приложение, которое генерирует свыше 5-10 000 строк данных в конкретной таблице для каждого сеанса пользователя. В настоящее время мы используем текстовые команды sql для вставки каждой строки данных за раз, поэтому операция сохранения может занять до минуты. Мы играем с использованием SqlBulkInserts и видим, что время сокращается до менее 500 мс. Кто-нибудь возражает против использования SqlBulkInserts в производственном приложении, где многие пользователи будут использовать эту систему?Использование SqlBulkInsert в производственных приложениях

ответ

6

Я никогда не сталкивался с проблемой с SqlBulkCopy с набором опций tableLock и другим пользователем, который был заблокирован из-за него. Опция TableLock повышает эффективность вставки из того, о чем говорили многие люди, и просто ее использование показало мне.

Мой типичный метод:

public void Bulk(String connectionString, DataTable data, String destinationTable) 
{ 
    using (SqlConnection connection = new SqlConnection(connectionString)) 
    { 
     using (SqlBulkCopy bulkCopy = 
      new SqlBulkCopy 
      (
      connection, 
      SqlBulkCopyOptions.TableLock | 
      SqlBulkCopyOptions.FireTriggers | 
      SqlBulkCopyOptions.UseInternalTransaction, 
      null 
      )) 
     { 
      bulkCopy.BatchSize = data.Rows.Count; 
      bulkCopy.DestinationTableName = String.Format("[{0}]", destinationTable); 
      connection.Open(); 
      bulkCopy.WriteToServer(data); 
     } 
    } 
} 
1

Я думаю, что это правильный путь, если вашему приложению действительно нужно произвести столько записей за сеанс.

+0

Благодаря тому, как наша база данных структурирована, у нас есть 12 таблиц, которые мы храним данные в одной транзакции, из-за этого мы получали ТУПИКИ ошибки при использовании SqlBulkCopy. Установив SqlBulkCopyOptions.TableLock, тупики ушли. Есть ли недостаток, заключающийся в блокировке таблицы для объемных вставок? Будет ли вред другим пользователям, пытающимся одновременно выполнить транзакцию? – PCG

+0

Ты имеешь в виду, что кроме тебя есть ТАБЛЫЙ БЛОК? рядом вы приходите и скуляете о наличии столовых замков;) Тупики - это совсем другое дело, и знак вашего программирования плохо сделан - устраняйте проблемы по мере их возникновения, не помещайте неправильный код на плохой код в симптомы avod. – TomTom

+0

Я бы полностью согласился с вами, если бы у меня не было менеджера продукта, кричащего по моей спине, чтобы не изменить ни одной вещи о схеме базы данных, кроме, возможно, некоторых индексов и сделать все лучше. Я был полностью взволнован всей ситуацией. – PCG

2

Перед реализацией с использованием SqlBulkInsert, попробуйте создать INSERT запрос динамически выглядеть следующим образом:

insert into MyTable (Column1, Column2) 
select 123, 'abc' 
union all 
select 124, 'def' 
union all 
select 125, 'yyy' 
union all 
select 126, 'zzz' 

Это будет только один вызов базы данных, которая должна работать гораздо быстрее. Для конкатенации строки SQL убедитесь, что вы используете класс StringBuilder.

+0

Я действительно занимался этой идеей, но моя проблема с этим подходом заключается в том, что мне нужно значение идентификатора, которое было создано для первичного ключа на сервере, когда мы строим дерево иерархии, поскольку это таблица саморегуляции. – PCG

+0

И что? Этот totlaly также исключает использование SqlBulkCopy - как вы делаете массовые вставки, если вам нужен идентификатор, сгенерированный сервером? Ответ верен, ваше одобрение противоречит вашему собственному заявлению. – TomTom

+0

Ваше право, и я идиот. То, что мы делаем в реализации SqlBulkCopy, - это получение списка данных, которые мы только что вставили на каждом уровне дерева, чтобы получить список генерируемых идентификаторов. Я даже не думал о том, чтобы делать то же самое, используя приведенное выше заявление. – PCG

Смежные вопросы