49 Stimmen

Ist es besser, viele SQL-Befehle mit einer Verbindung auszuführen oder jedes Mal eine neue Verbindung herzustellen?

Hier ist mein Testcode, der darauf hindeutet, dass es besser ist, mehrere Verbindungen herzustellen, anstatt nur eine.

Mache ich etwas falsch?

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

Ausgabe:

//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

Aktualisierung:

OK, diejenigen, die sagten, dass es mit einer Verbindung schneller geht, haben es also. (obwohl der Unterschied nur marginal ist, wenn überhaupt). Hier ist der überarbeitete Code und die Ausgabe:

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

Ausgabe:

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

Aktualisierung:

der Unterschied ist deutlicher, wenn ich die SQLConnection.ClearAllPools() nach jeder Funktion:

Ausgabe:

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

34voto

Ben Schwehn Punkte 4459

Standardmäßig verwendet SqlConnection das Pooling von Verbindungen. Daher öffnet Ihr Code in beiden Fällen höchstwahrscheinlich nicht wirklich viele Verbindungen.

Sie können steuern, ob SqlConnection Pooling verwendet, indem Sie den Pool im Connectionstring aktivieren oder deaktivieren. Je nachdem, für welche DB Ihr Connectionstring ist, variiert die Syntax.

Siehe aquí für einige Informationen, wenn Sie MSSQLServer verwenden. Versuchen Sie, Pooling=false in der Verbindungszeichenfolge zu setzen und sehen Sie, ob dies einen Unterschied macht.

12voto

Adriano Carneiro Punkte 56027

Es ist auf jeden Fall besser, eine Verbindung zu haben. Vielleicht führen Sie Ihren Benchmark mit einer geringen Datenmenge durch. Versuchen Sie, die Anzahl auf 1.000 oder 10.000 zu erhöhen.

Ein weiterer Punkt ist, dass Sie je nach Konfiguration Ihrer Anwendung denken könnten, dass Sie mit mehreren Verbindungen arbeiten, aber .NET poolt die Verbindungen für Sie, so dass Sie im Grunde mit denselben Verbindungen arbeiten.

8voto

Groo Punkte 47623

Da .NET Verbindungen wiederverwendet ("connection pooling"), ist der Aufwand für die Erstellung einer neuen Instanz von DbConnection mehrere Male hintereinander. ADO.NET verwendet die Verbindung unter der Haube einfach wieder. Deshalb ist es gut, dass Sie die SqlConnection Objekt jedes Mal, um .NET mitzuteilen, dass es es an den Pool zurückgeben kann.

Sie können jedoch die Leistung bei mehreren Einfügungen erhöhen, indem Sie ADO.NET-Stapelverarbeitung . In diesem Fall können Sie leicht mehrere Tausende der Einsätze pro Sekunde. Wenn die Leistung entscheidend ist, können Sie sogar die Verwendung von SQLBulkCopy .

Auch Ihr erstes Paar Ergebnisse ist recht merkwürdig: 30s für 100 Einsätze?

5voto

n8wrl Punkte 19091

In der Regel sollte .NET's Verbindungspooling es "egal" machen, da es eine große Arbeit der Wiederverwendung von Verbindungen für Sie tut. Aber meine Praxis ist es, eine einzige Verbindung für eine Reihe von Transaktionen zu verwenden, von denen ich weiß, dass sie zusammen stattfinden werden. Ich denke, Ihre Zeitangaben sind ein Hinweis darauf, dass der Verbindungspool seine Aufgabe erfüllt und dass es einfach Schwankungen bei den Ausführungen gibt.

3voto

James Kovacs Punkte 11419

SqlClient wird Ihre Verbindungen zusammenfassen. Im ersten Fall, in dem Sie eine Verbindung geöffnet haben, wird sie die Verbindung öffnen. Bei jedem weiteren Lauf wird die gepoolte Verbindung verwendet. Wenn Sie Ihre Reihenfolge umkehren und "viele Verbindungen" zuerst ausführen, würde ich erwarten, dass Sie das gegenteilige Ergebnis sehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X