Comment puis-je accélérer cette fonction C # / insertion SQL?

Ce code sérialise un tableau d'entiers puis l'insère dans une table sql. Ce n'est pas aussi rapide que j'en ai besoin. Pourrais-je faire quelque chose de plus efficacement?

Merci!

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(); } } } 

Je vous conseille de split cette fonction en deux. L'un concerne le tableau d'octets l'autre pour l'insertion dans la database.

Ensuite, exécutez le profilage et voyez si le code du tableau d'octets est lent ou s'il s'agit d'un problème de database.

Peut-être que vous essayez d'accélérer quelque chose qui n'est pas lent 🙂

Si vous insérez beaucoup de lignes, la class SqlBulkCopy est beaucoup plus rapide que l' insert appels SqlBulkCopy . Voir ce billet de blog pour un exemple .

La première chose que j'essaierais est la pré-allocation de byte[] pour le stream memory:

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

Vous pouvez créer une procédure avec la command insert. C'est plus rapide car la procédure est déjà compilée pour Sql

Quelque chose comme ça:

  SqlConnection conn = new SqlConnection(actual_ssortingng); conn.Open(); // Create the command ssortingng 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(); } 

Mais ma preference est d'envoyer un XML à une procédure.

Vous pourriez en voir plus dans ce bon article

Ma première inclination serait de BinaryWriter un tableau à utiliser par le MemoryStream , puis d'utiliser BinaryWriter pour y écrire:

 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 n'utilise pas BitConverter.GetBytes interne. Au contraire, il extrait les octets un à la fois de l' int et les place dans un tampon. Ensuite, le tampon est écrit dans le stream. BitConverter , d'autre part, alloue un nouveau tampon de 4 octets chaque fois que vous l'appelez.