2015-01-11 6 views
1

У меня есть пара таблиц с ограничениями первичного ключа, которые я заполняю из C#.Самый быстрый способ вставки строк без нарушения первичного ключа

Каким будет самый быстрый способ вставки строк без нарушения первичного ключа?

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

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

1.

foreach(var point in points) 
{ 
    ... 
    sqlCommand.ExecuteNonQuery(@" 
    BEGIN TRY 
     INSERT INTO POINTS ... 
    END TRY 
    BEGIN CATCH 
     IF ERROR_NUMBER() <> 2627 
     BEGIN 
      THROW 
     END 
    END CATCH", con) 
} 

2.

foreach(var point in points) 
{ 
    ... 
    sqlCommand.ExecuteNonQuery(@" 
    IF NOT EXISTS (Select 1 from POINTS where ...) 
    INSERT INTO POINTS ...", con) 
} 

3.

StringBuilder sb = new StringBuilder(); 
sb.AppendLine("BEGIN TRAN"); 
foreach(var point in points) 
{ 
    sb.AppendLine("IF NOT EXISTS (Select 1 from POINTS where ...) INSERT INTO POINTS ...") 
} 
sb.AppendLine("COMMIT TRAN"); 
sqlCommand.ExecuteNonQuery(sb.ToString()); 

4.

StringBuilder sb = new StringBuilder(); 
sb.AppendLine(@" 
    BEGIN TRAN 
    DECLARE @POINTS TABLE (
    ... 
    ) 
"); 
foreach(var point in points) 
{ 
    sb.AppendLine("INSERT INTO @POINTS ...") 
} 
sb.AppendLine(@" 
    MERGE POINTS as T 
    USING @POINTS as S 
    ON T.KEY=S.KEY 
    WHEN OT MATCHED THEN 
    INSERT ... 
"); 
sb.AppendLine("COMMIT TRAN"); 
sqlCommand.ExecuteNonQuery(sb.ToString()); 

ответ

6

Если ваш почтовый ints большой, рассмотрите возможность использования SqlBulkCopy, чтобы вставить его в временную таблицу (например, #NEW_POINTS) сначала. Таким образом, вы избежите запуска отдельного оператора INSERT для каждой точки.

Затем запустите одиночный MERGE или комбинацию INSERT/UPDATE, чтобы переместить данные в вашу фактическую таблицу POINTS.

+0

Это самый эффективный способ. Просто вставьте его в таблицу хранения в базе данных, затем вы можете использовать все команды на основе SQL, чтобы массировать данные в ваши живые таблицы. – dbugger

+0

Таким образом, объединение между #NEW_POINTS и таблицей POINTS будет работать лучше, чем с переменной @POINTS? Я думал, что из-за того, что слияние является одним из фильтрующих строк, производительность вставки внутри временного значения ничтожно мала. – adrianvlupu

+0

Я бы ожидал, что MERGE выполнит то же самое, независимо от того, использует ли таблица temp #POINTS или переменную @POINTS. Однако использование SqlBulkCopy почти наверняка будет быстрее, чем НАСЫЩЕНИЕ точек отдельно (foreach (точка в точках в точках) ...). – Max

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