0

Ich habe diese Java-Webapp, die zu viel mit einer SQL Server-Datenbank kommunizieren. Ich möchte entscheiden, wie die Verbindungen zu dieser Datenbank auf effiziente Weise verwaltet werden. Die erste Option, die Ihnen in den Sinn kommt, ist die Verwendung von Drittanbietern, die Verbindungen aufbauen. Ich wählte C3P0 und DBCP und einige Testfälle vorbereitet, diese Ansätze zu vergleichen, wie folgt:JDBC Verbindungspooling für SQL Server: DBCP vs C3P0 vs keine Pooling

Nein Pooling:

public static void main(String[] args) { 
     long startTime=System.currentTimeMillis(); 
     try { 
      for (int i = 0; i < 100; i++) { 
       Connection conn = ConnectionManager_SQL.getInstance().getConnection(); 

       String query = "SELECT * FROM MyTable;"; 
       PreparedStatement prest = conn.prepareStatement(query); 

       ResultSet rs = prest.executeQuery(); 
       if (rs.next()) { 
        System.out.println(i + ": " + rs.getString("CorpName")); 
       } 
       conn.close(); 
      } 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs"); 
    } 

DBCP:

public static void main(String[] args) { 
     long startTime=System.currentTimeMillis(); 
     try { 
      for (int i = 0; i < 100; i++) { 
       Connection conn = ConnectionManager_SQL_DBCP.getInstance().getConnection(); 

       String query = "SELECT * FROM MyTable;"; 
       PreparedStatement prest = conn.prepareStatement(query); 

       ResultSet rs = prest.executeQuery(); 
       if (rs.next()) { 
        System.out.println(i + ": " + rs.getString("CorpName")); 
       } 
       conn.close(); 
      } 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs"); 
    } 

C3P0:

public static void main(String[] args) { 
     long startTime=System.currentTimeMillis(); 
     try { 
      for (int i = 0; i < 100; i++) { 
       Connection conn = ConnectionManager_SQL_C3P0.getInstance().getConnection(); 

       String query = "SELECT * FROM MyTable;"; 
       PreparedStatement prest = conn.prepareStatement(query); 

       ResultSet rs = prest.executeQuery(); 
       if (rs.next()) { 
        System.out.println(i + ": " + rs.getString("CorpName")); 
       } 
       conn.close(); 
      } 
     } catch (Exception e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("Finished in: "+(System.currentTimeMillis()-startTime)+" milli secs"); 
    } 

Und Hier sind die Ergebnisse:

Max Pool size for c3p0 and dbcp=10 
c3p0: 5534 milli secs 
dbcp: 4807 milli secs 
No Pooling: 2660 milli secs 

__

Max Pool size for c3p0 and dbcp=100 
c3p0: 4937 milli secs 
dbcp: 4798 milli secs 
No Pooling: 2660 milli secs 

Man könnte sagen, die Initialisierung und Startzeitbibliotheken zu bündeln könnten die Ergebnisse dieser Testfälle betreffen. Ich habe sie mit größeren Zahlen in der Schleife wiederholt und die Ergebnisse sind fast gleich.

Überraschenderweise ist der Ansatz ohne Pooling viel schneller als die Verbindungs-Pooling-Methoden. Während ich annehme, wenn wir eine Verbindung physisch schließen, muss ein neuer zeitaufwendiger sein.

Also, was ist hier los?

EDIT_01: c3p0 und dbcp Konfigurationen

c3p0:

cpds.setMinPoolSize(5); 
cpds.setAcquireIncrement(5); 
cpds.setMaxPoolSize(100); 
cpds.setMaxStatements(1000); 

dbcp:

basicDataSource.setMinIdle(5); 
basicDataSource.setMaxIdle(30); 
basicDataSource.setMaxTotal(100); 
basicDataSource.setMaxOpenPreparedStatements(180); 

Die übrigen Konfigurationen als Standard bleiben. Erwähnenswert ist, dass alle Verbindungen für eine DB auf localhost aufgebaut sind.

+0

Sie verwenden nur jeweils eine Verbindung, wodurch sich der Nutzen eines Verbindungspools verringert. Sie haben auch nicht die Konfiguration Ihres Verbindungspools angezeigt (zB Timeouts, Min/Max-Größe, ist Ihre Verbindung zu localhost, oder ein Remote-Server, etc.). –

+0

@MarkRotteveel Überprüfen Sie die Edit_01. –

Antwort

4

c3p0 ist nicht dader als eine Türnagel. Es ist alt, aber (etwas) aktiv gepflegt. Ob neue Alternativen für Ihre Anwendung besser geeignet sind, entscheiden Sie selbst.

Welche Version von c3p0 verwenden Sie? Wenn Sie denken, dass es düsterer ist als ein Türnagel, verwenden Sie eine alte Version? Sie sollten 0.9.5.2 verwenden.

Das Ergebnis des Tests, wie Sie es definiert haben, hängt stark von vielen Dingen ab, die mit den von Ihnen bereitgestellten Informationen schwer zu bewerten sind. Wie Mark Rotteveel hervorhebt, haben Sie keine Informationen über Ihre Konfiguration angezeigt. Sie haben nichts über den Speicherort von SQL Server gesagt. Sie werden einen größeren Nutzen aus einem Verbindungspool feststellen, wenn die Datenbank remote ist, als wenn es sich um eine lokale Datenbank handelt, da sich die Leistungsverbesserung zum Teil aus der amortisierten Netzwerklatenz der Connection-Erfassung über mehrere Clientanwendungen ergibt. Ihr Test führt eine Abfrage aus und durchläuft die Ergebnismenge. Je länger die Ergebnismenge ist, desto mehr Overhead aus dem Verbindungspool (der das ResultSet-Proxy verwenden muss) wird die Vorteile der schnelleren Connection-Erfassung übertreffen. (Die Zahlen, die Sie erhalten, sehen jedoch ungewöhnlich schlecht aus. C3p0 hat in der Regel eine sehr schnelle ResultSet-Passthrough-Leistung.) Bei ausreichend langen Abfragen werden die Kosten der Connection-Erfassung vernachlässigbar, wenn der Overhead der Pooling-Bibliothek bei der Iteration durch ein ResultSet zunimmt, was einen Connection-Pool nicht so nützlich macht.

Aber das ist bei weitem nicht der typische Anwendungsfall für Web- oder mobile Clients, die normalerweise kurze Abfragen, Einfügungen und Aktualisierungen vornehmen. Bei kurzen Abfragen, Einfügungen und Aktualisierungen können die Kosten einer de novo Verbindungserfassung relativ zur Ausführung der Abfrage sehr groß sein. Dies ist der Anwendungsfall, für den Verbindungspools eine große Verbesserung bieten. Das ist vielleicht nicht das, was Sie testen. es hängt davon ab, wie groß MyTable ist.

+0

Nun, ich habe vielleicht über c3p0 übertrieben. Es ist ein gutes Werkzeug (nicht das Beste heutzutage), aber soweit ich weiß, hat es sich in den letzten Jahren nicht wesentlich verändert. Die Maven Repo-Version kehrt zu 2007 zurück, aber ich verwende die neueste Version, 0.9.5.2. Entschuldigung, wenn Sie irgendwelche Zugehörigkeiten zu diesem Produkt haben. Erklären Sie über den ursprünglichen Zweck dieser Frage im nächsten Kommentar ... –

+0

Nun ich nicht durch die Ergebnismenge iterieren, ich hole nur den ersten Datensatz (if (rs.next()) ...). Ich nahm an, dass dies die Gültigkeit des Tests nicht beeinflussen würde, da es für alle Fälle das gleiche Ergebnis liefert. Und was hier anders zu bleiben scheint, sind die Kosten für den Aufbau einer neuen Verbindung. Was ich verpasste, ist die Tatsache, dass Verbindungs-Pooling-Tools die Ergebnismenge als Proxy verwenden und dies einen zusätzlichen Aufwand beim Abrufen der Daten verursacht. Obwohl ich nicht über das gesamte Ergebnis iteriere, scheint es, dass Verbindungspools die gesamte Ergebnismenge verarbeiten. Die Tabelle, die ich abfrage, hat ungefähr 8k Datensätze ... –

+0

und die Größe der Tabelle wirkt sich auf die Leistung des Verbindungspools aus. Ich änderte die Abfrage, um den TOP 1-Datensatz auszuwählen und erhielt die erwarteten Ergebnisse. –

Verwandte Themen