簡體   English   中英

使用一個連接執行多個sql命令或每次重新連接是否更好?

[英]Is it better to execute many sql commands with one connection, or reconnect every time?

這是我的測試代碼,它似乎表明連接多次而不是僅連接一次更好。

難道我做錯了什么?

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

默認情況下,SqlConnection將使用連接池。 因此,在任何一種情況下,您的代碼很可能不會實際打開許多連接。

您可以通過在連接字符串中啟用或禁用池來控制SqlConnection是否將使用池,具體取決於連接字符串所用的DB,語法將有所不同。

如果您使用MSSQLServer,請參閱此處獲取一些信息。 嘗試在連接字符串中設置Pooling = false,看看它是否有所不同。

確切地說,最好有一個連接。 也許您正在使用少量數據運行基准測試。 嘗試將數字增加到1,000或10,000。

另一點是,根據您的應用程序配置,您可能認為您正在運行多個連接,但.NET正在為您匯集連接,因此您基本上使用相同的連接運行。

由於.NET重用連接(“連接池”),因此在連續多次創建DbConnection的新實例時沒有太多開銷。 ADO.NET將重用引擎蓋下的連接。 這就是為什么每次處理SqlConnection對象都很好,告訴.NET它可以將它返回到池中。

但是,您可以通過使用ADO.NET批處理來提高多個插入的性能。 在這種情況下,您每秒可以輕松地擁有數千個插入。 如果性能至關重要,您甚至可以考慮使用SQLBulkCopy

另外,你的第一對結果很奇怪:100個插入30秒?

一般來說,.NET的連接池應該使它“無關緊要”,因為它可以很好地為您回收連接。 但我的做法是使用一個連接來處理我知道將要一起進行的一系列事務。 我認為您的計時表明連接池正在完成其工作,而且只是運行中的簡單變化。

SqlClient將匯集您的連接。 在你打開連接的第一種情況下,它將完成打開連接的工作。 每次運行都將使用池化連接。 如果你顛倒你的訂單並先做“多次聯系”,我希望你能看到相反的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM