c#-一次连接执行多个sql命令或每次重新连接是否更好?

这是我的测试代码,似乎暗示多次连接比一次连接更好。

难道我做错了什么?

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

更新:

好的,所以那些说使用一个连接会更快的人有了它。 (尽管相差不大,如果有的话。)这是修改后的代码和输出:

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
5个解决方案
33 votes

默认情况下,SqlConnection将使用连接池。 因此,无论哪种情况,您的代码很可能实际上并未打开许多连接。

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

如果您使用MSSQLServer,请参见此处获取一些信息。 尝试在连接字符串中设置Pooling = false,看看是否有所不同。

Ben Schwehn answered 2020-08-10T22:23:50Z
10 votes

绝对地,最好有一个连接。 也许您正在使用少量数据运行基准测试。 尝试将数字增加到1,000或10,000。

另一点是,根据您的应用程序配置,您可能会认为您正在使用多个连接运行,但是.NET为您池化了连接,因此您基本上是在相同的连接下运行。

Adrian Carneiro answered 2020-08-10T22:24:15Z
7 votes

由于.NET重用连接(“连接池”),因此连续创建几次新的SQLBulkCopy实例不会产生太多开销。 ADO.NET只会在后台重用连接。 这就是为什么每次都放置SqlConnection对象并告诉.NET它可以将其返回到池中是件好事的原因。

但是,可以使用ADO.NET批处理来提高多个插入的性能。 在这种情况下,您可以轻松地每秒拥有数千个刀片。 如果性能至关重要,您甚至可以考虑使用SQLBulkCopy

另外,您的第一对结果非常奇怪:100次插入30秒?

Groo answered 2020-08-10T22:24:44Z
3 votes

通常,.NET的连接池应使其“无关紧要”,因为它为您回收了很多连接。 但是我的做法是对一个我知道将一起进行的交易使用单个连接。 我认为您的时间安排表明连接池正在执行其工作,并且只是运行中的明显变化。

n8wrl answered 2020-08-10T22:25:04Z
3 votes

SqlClient将合并您的连接。 在您的第一个打开状态下,它将完成打开连接的工作。 其他所有运行将使用池化连接。 如果您撤消订单并首先执行“许多连接”,我希望您看到相反的结果。

James Kovacs answered 2020-08-10T22:25:24Z
translate from https://stackoverflow.com:/questions/5981376/is-it-better-to-execute-many-sql-commands-with-one-connection-or-reconnect-ever