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.