2011-03-30 2 views
4

Этот код сериализует массив целых чисел, а затем вставляет его в таблицу sql. Это не так быстро, как мне нужно. Могу ли я сделать что-нибудь более эффективно?Как я могу ускорить эту функцию C#/SQL-вставку?

Спасибо!

public void SetItem(long Id, int[] items) 
    { 
     using (MemoryStream stream = new MemoryStream()) 
     { 
      foreach (int d in items) 
      { 
       var bin = BitConverter.GetBytes(d); //Serialize 
       stream.Write(bin, 0, bin.Length); 
      } 
      var array = stream.ToArray(); 

      using (SqlCommand cmd = new SqlCommand("INSERT INTO Items(Id, Item, DateCreated) VALUES (@Id, @binaryValue, @dateCreated)", sqlConnection)) 
      { 
       cmd.Parameters.Add("@binaryValue", SqlDbType.VarBinary, array.Length).Value = array; 
       cmd.Parameters.Add("@Id", SqlDbType.BigInt).Value = Id; 
       cmd.Parameters.Add("@dateCreated", SqlDbType.DateTime2).Value = DateTime.Now; 
       cmd.ExecuteNonQuery(); 
      } 
     } 
    } 
+0

Вы пытались обернуть BinaryWriter вокруг MemoryStream, а не использовать BitConverter? Кроме того, поскольку вы конвертируете его в массив в конце, зачем использовать Stream, а не массив? Вы уже знаете размер (items.Count * 4) –

+0

Является ли sqlConnection частной переменной? – rsbarro

+0

Да, sqlConnection является переменной prvate. – user404068

ответ

10

Советую разделить эту функцию на две части. Один для байтового массива - другой для вставки в БД.

Затем запустите профилирование и посмотрите, не слишком ли задан байтовый массив, или если это проблема с db.

Может быть, вы пытаетесь ускорить то, что не замедлит :)

1

Первое, что я хотел бы попробовать это из byte[] Предварительное выделение для потока памяти:

var array = new int[BitConverter.GetBytes(0).Length * items.Length]; 
using (MemoryStream stream = new MemoryStream(array)) 
{ 
    // ... rest is almost the same 
} 
1

Вы можете создать процедуру, с вставить команду. Это быстрее, потому что процедура уже скомпилированные для Sql

Что-то вроде этого:

SqlConnection conn = new SqlConnection(actual_string); 
conn.Open(); 

// Create the command string 
SqlCommand cmd = new SqlCommand("EXEC insert_test @var1, @var2, @var3, @str1, @str2", conn); 

// Iterate through all of the objects 
try { 
    for (int i = 0; i < 10000; i++) { 
     cmd.Parameters.Clear(); 
     cmd.Parameters.Add(new SqlParameter("@var1", var1)); 
     cmd.Parameters.Add(new SqlParameter("@var2", var2)); 
     cmd.Parameters.Add(new SqlParameter("@var3", var3)); 
     cmd.Parameters.Add(new SqlParameter("@str1", str1)); 
     cmd.Parameters.Add(new SqlParameter("@str2", str2)); 

     // Read in all the data 
     cmd.ExecuteNonQuery(); 
    } 
} finally { 
    conn.Close(); 
} 

Но я предпочитаю, чтобы отправить XML в порядке.

Вы могли видеть больше в этом good article

6

Если вы вставив много строк, то SqlBulkCopy класс намного быстрее, чем вызов insert много раз. См. Это blog post for an example.

+0

Мне тоже нравится этот подход. –

+0

uhm ... он делает единственную вставку – BlackTigerX

1

Мой первый наклон будет предварительно выделить массив, который будет использоваться в MemoryStream, а затем использовать BinaryWriter, чтобы писать:

var OutputArray = new byte[items.Length * 4]; 
using (var ms = new MemoryStream(OutputArray)) 
{ 
    using (var writer = new BinaryWriter(ms)) 
    { 
     foreach (var i in items) 
     { 
      writer.Write(i); 
     } 
    } 
} 
// You can now send the OutputArray to SQL server 

BinaryWriter не использует BitConverter.GetBytes внутренне. Скорее, он извлекает байты по одному из int и помещает их в буфер. Затем буфер записывается в поток. С другой стороны, BitConverter выделяет новый 4-байтовый буфер каждый раз, когда вы его вызываете.

+0

, это немного быстрее, спасибо – user404068

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