0

SQL Server 데이터베이스와 너무 많이 통신하는 Java Webapp가 있습니다. 이 DB에 대한 연결을 효율적으로 관리하는 방법을 결정하고 싶습니다. 마음에 드는 첫 번째 옵션은 연결 풀링 타사를 사용하는 것입니다. 내가 C3P0와 DBCP를 선택하고 다음과 같이 이러한 접근 방식을 비교하기 위해 몇 가지 테스트 케이스를 준비 :SQL Server 용 JDBC 연결 풀링 : DBCP와 C3P0 및 풀링 없음

없음 풀링 :

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

그리고 결과는 다음과 같습니다.

0 1,236,489,146,624,418,196,406,463,210

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

하나는 이러한 테스트 케이스의 결과에 영향을 미칠 수있는 라이브러리를 풀링의 초기화 및 시작 시간을 말할 수 __. 루프에서 큰 숫자로 반복했으며 결과는 거의 같습니다.

놀랍게도 풀링없는 방법은 연결 풀링 방법보다 훨씬 빠릅니다. 우리가 물리적으로 연결을 닫을 때 나는 생각하지만, 새로운 연결을 얻는 것은 더 많은 시간을 소비해야합니다.

여기에 무슨 일이 발생합니까?

EDIT_01 : C3P0와 DBCP 구성

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

구성의 나머지는 기본값으로 남아 있습니다. 모든 연결은 localhost의 DB에 대해 설정된다는 것에 주목해야합니다.

+0

한 번에 하나의 연결 만 사용하므로 연결 풀의 유용성이 줄어 듭니다. 또한 연결 풀 구성을 표시하지 않았습니다 (예 : 제한 시간, 최소/최대 크기, 로컬 호스트 연결 또는 원격 서버 등). –

+0

@MarkRotteveel Edit_01을 확인하십시오. –

답변

4

c3p0은 doornail보다 작지 않습니다. 그것은 오래되었지만 (다소) 적극적으로 유지되었습니다. 더 새로운 대안이 귀하의 신청에 더 잘 부합하는지 여부는 귀하가 결정하는 것입니다.

어떤 버전의 c3p0을 사용하고 있습니까? 당신이 doornail보다 더 이상하다고 생각한다면, 이전 버전을 사용하고 있습니까? 0.9.5.2를 사용해야합니다.

정의한대로 테스트 결과는 제공 한 정보로는 평가하기 어려운 많은 것들에 크게 의존하게됩니다. Mark Rotteveel이 지적했듯이 설정에 대한 정보는 표시하지 않았습니다. SQL Server의 위치에 대해서는 언급하지 않았습니다. 성능 향상의 일부는 여러 클라이언트가 사용하는 동안 Connection 획득의 네트워크 대기 시간을 상환하는 것으로부터 얻을 수 있기 때문에 데이터베이스가 로컬 인 경우보다 연결 풀에서 더 많은 이점을 얻을 수 있습니다. 테스트는 쿼리를 실행하고 결과 집합을 반복합니다. 결과 집합이 길어질수록 Connection 풀 (ResultSet을 프록시해야 함)에서 오버 헤드가 더 많이 표시되어 Connection을 더 빨리 획득 할 수 있다는 이점을 능가합니다. c3p0은 일반적으로 매우 빠른 ResultSet 패스 스루 성능을 가지고 있습니다.) 충분히 긴 질의를 사용하면 Connection 획득 비용은 무시할 수 있습니다. ResultSet을 반복하면 풀링 라이브러리의 오버 헤드가 증가하여 연결 풀이별로 유용하지 않습니다.

그러나 이것은 일반적으로 짧은 쿼리, 삽입 및 업데이트를하는 웹 또는 모바일 클라이언트의 일반적인 사용 사례와 다릅니다. 짧은 쿼리, 삽입 및 업데이트의 경우 de novo 연결 획득 비용은 쿼리 실행에 비해 매우 클 수 있습니다. 이것은 연결 풀이 큰 개선을 제공하는 유스 케이스입니다. 그것은 당신이 테스트하고있는 것이 아닐 수도 있습니다. 얼마나 큰지에 따라 다릅니다 MyTable입니다.

+0

글쎄, 나는 c3p0에 대해 과장했을 것이다. 그것은 좋은 도구 (요즘은 최고는 아니지만) 내가 아는 한 지난 몇 년 동안 크게 변화하지 않았습니다. Maven Repo 버전은 2007로 돌아가지만 최신 버전 인 0.9.5.2를 사용하고 있습니다. 해당 제품과 제휴 관계가있는 경우 사과드립니다. 다음 질문에이 질문의 원래 목적에 대해 설명합니다 ... –

+0

글쎄, 결과 세트를 반복하지 않고, (rs.next()) ...) 첫 번째 레코드 만 가져옵니다. 나는 이것이 모든 경우에 대해 동일한 결과를 반환하기 때문에 이것이 테스트의 유효성에 영향을 미치지 않는다고 가정했다. 여기에 다른 것으로 남아있는 것은 새로운 연결을 구축하는 데 드는 비용입니다. 내가 놓친 것은 연결 풀링 도구가 결과 집합을 프록시 처리하므로 데이터를 가져 오는 데 추가 오버 헤드가 부과된다는 사실입니다. 모든 결과를 반복하지는 않지만 연결 풀이 전체 결과 집합을 처리하는 것처럼 보입니다. 쿼리하는 테이블에는 약 8k 개의 레코드가 있습니다 ... –

+0

및 테이블 크기는 연결 풀링 도구의 성능에 영향을줍니다. TOP 1 레코드를 선택하기 위해 쿼리를 변경하고 예상되는 결과를 얻었습니다. –