用一个连接执行多个sql命令更好吗,还是每次都重新连接?

这里是我的testing代码,这似乎表明最好连接多次而不是连接一次。

难道我做错了什么?

int numIts = 100; Stopwatch sw = new Stopwatch(); sw.Start(); using (SqlConnection connection = new SqlConnection(connectionParameters)) { connection.Open(); for(int i = 0; i < numIts; i++) { SqlCommand command = new SqlCommand(sqlCommandName, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue(par1Name, par1Val); command.Parameters.AddWithValue(par2Name, par2Val); using(SqlDataReader reader = command.ExecuteReader()) { } } } sw.Stop(); TimeSpan durationOfOneConnectionManyCommands = sw.Elapsed; Console.WriteLine(durationOfOneConnectionManyCommands); sw.Reset(); sw.Start(); for(int i = 0; i < numIts; i++) { using (SqlConnection connection = new SqlConnection(connectionParameters)) { connection.Open(); SqlCommand command = new SqlCommand(sqlCommandName, connection); command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue(par1Name, par1Val); command.Parameters.AddWithValue(par2Name, par2Val); using(SqlDataReader reader = command.ExecuteReader()) { } } } sw.Stop(); TimeSpan durationOfManyConnections = sw.Elapsed; Console.WriteLine(durationOfManyConnections); 

输出:

 //output: //00:00:24.3898218 // only one connection established //00:00:23.4585797 // many connections established. // //output after varying parameters (expected much shorter): //00:00:03.8995448 //00:00:03.4539567 

更新:

好的,那些说这样的话会更快一些。 (尽pipe差异很小,如果有的话)。下面是修改过的代码和输出:

 public void TimingTest() { numIts = 1000; commandTxt = "select " + colNames + " from " + tableName; OneConnection(); ManyConnections(); OneConnection(); } private void ManyConnections() { Stopwatch sw = new Stopwatch(); sw.Start(); for (int i = 0; i < numIts; i++) { using (SqlConnection connection = new SqlConnection(connectionParameters)) { connection.Open(); using (SqlCommand command = connection.CreateCommand()) { command.CommandText = commandTxt; using (SqlDataReader reader = command.ExecuteReader()) { } } } } sw.Stop(); TimeSpan durationOfManyConnections = sw.Elapsed; Console.WriteLine("many connections: " + durationOfManyConnections); } private void OneConnection() { Stopwatch sw = new Stopwatch(); sw.Start(); using (SqlConnection connection = new SqlConnection(connectionParameters)) { connection.Open(); for (int i = 0; i < numIts; i++) { using (SqlCommand command = connection.CreateCommand()) { command.CommandText = commandTxt; using (SqlDataReader reader = command.ExecuteReader()) { } } } } sw.Stop(); TimeSpan durationOfOneConnectionManyCommands = sw.Elapsed; Console.WriteLine("one connection: " + durationOfOneConnectionManyCommands); } 

输出:

 one connection: 00:00:08.0410024 many connections: 00:00:08.7278090 one connection: 00:00:08.6368853 one connection: 00:00:10.7965324 many connections: 00:00:10.8674326 one connection: 00:00:08.6346272 

更新:

如果我在每个函数之后使用SQLConnection.ClearAllPools() ,则区别更加显着:

输出:

 one connection: 00:00:09.8544728 many connections: 00:00:11.4967753 one connection: 00:00:09.7775865 

默认情况下,SqlConnection将使用连接池。 因此,在任何情况下,您的代码很可能不会实际打开许多连接。

您可以通过启用或禁用连接string中的池来控制SqlConnection是否将使用池,具体取决于连接string的用途,语法会有所不同。

如果您使用MSSQLServer,请参阅这里获取一些信息。 尝试在连接string中设置Pooling = false,看看它是否有所作为。

明确地说,最好有一个连接。 也许你正在用less量的数据运行你的基准testing。 尝试增加到1000或10,000。

还有一点是,根据你的应用程序configuration,你可能会认为你正在运行多个连接,但是.NET为你build立连接,所以你基本上运行着相同的连接。

由于.NET重用了连接(“连接池”),所以在连续多次创build一个新的DbConnection实例时没有太多开销。 ADO.NET将会重新使用这个连接。 这就是为什么每次都要处理SqlConnection对象,告诉.NET可以将它返回给池。

但是,您可以通过使用ADO.NET批处理来提高多个插入的性能。 在这种情况下,你可以很容易地每秒钟有几千个插入。 如果性能至关重要,则可以考虑使用SQLBulkCopy

另外,你的第一对结果是相当奇怪的:100个插入30秒?

一般来说,.NET的连接池应该是“无关紧要”,因为它为你回收连接做了很好的工作。 但我的做法是使用一个单一的连接,我知道将会一起发生的一堆交易。 我认为你的时间表明了连接池的function,以及运行中的简单变化。

SqlClient将会连接你的连接。 在第一种情况下,打开连接就可以了。 每隔一次运行将使用池连接。 如果你反转你的订单,先做“多个连接”,我希望你看到相反的结果。