2009-08-06 3 views
2

테이블에서 6 백만 행을 가진 하나의 열을 선택하고 많은 CPU 시간이 소요되는 Java 웹 응용 프로그램이 있습니다. 이 select (select id from FROM mytable WHERE filename = 'unique_filename')는 쿼리 브라우저에서 실행될 때 시간이 훨씬 적습니다.왜 SQL select가 java에서 더 많은 CPU 시간을 필요로합니까?

어떻게 될 수 있습니까?
어디에서 병목 현상을 찾아야합니까? 데이터베이스 개체를 연결 개체를받을 DriverManager를 사용

ResultSet rs = null;  
PreparedStatement stmt = null; 
Connection conn = null; 
Integer myId=null; 
String myVeryUniqueFileName = strFromSomeWhere; 
try 
{ 
    conn = Database.getConnection(); 
    stmt = conn.prepareStatement("SELECT id FROM mytable WHERE filename = ?"); 
    stmt.setString(1, myVeryUniqueFileName); 

    rs = stmt.executeQuery(); 
    if (rs.next()) 
    { 
     myId= new Integer(rs.getInt(1)); 
    }    } 
    if (rs.next()) 
    { 
     throw new DBException("Duplicate myId: " + myId); 
    } 
    return myId; 
} catch (Exception e) { 
    // handle this 
} 


1.Java 코드 :

데이터베이스 자바 컨테이너 (sqljdbc 1.2) 톰캣 5.5

자세한 내용입니다 MSSQL 2005 표준
입니다 .

2.SQL 테이블에는 약 30 개의 열이 있습니다.

CREATE TABLE [dbo].[calls]( 
    [id] [int] NOT NULL,  
    ...  
    [filename] [varchar](50) NOT NULL, 
    ...  
CONSTRAINT [PK_xxxxxxxxxxxx] PRIMARY KEY CLUSTERED  
( 
    [id] ASC  
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY],  
CONSTRAINT [UQ_xxxxxxxxxxxx] UNIQUE NONCLUSTERED  
(  
    [filename] ASC  
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]  
) ON [PRIMARY]  

파일 이름 열은 고유하므로 결과 집합은 allways 1 또는 null입니다.

+1

당신이 CPU 시간을 말할 때, 당신은 자바가 사용하는 CPU를 의미합니까 응용 프로그램 또는 데이터베이스 서버에서 사용하는 CPU? 그들은 두 개의 다른 기계에 있습니까? –

+0

Tomcat과 MSSQL이 같은 서버에 있습니까? 어떤 객체에서 Java 응용 프로그램이 600 만 개의 ID 값을 저장합니까? .NET뿐만 아니라 Java도 메모리의 각 객체를 만들고 파괴 할 시간이 필요하며 6 백만 개의 객체를 만들어야하는 경우 많은 시간이 필요합니다. –

+0

어떻게 이것이 진짜 질문이 아닌가요? 매우 자세한 것은 아니지만 영업 담당자는 여전히이를 수정할 수 있습니다. – ChssPly76

답변

2

더 똑똑한 개발자의 도움으로이 문제를 해결할 수있었습니다. PreparedStatement (aricle)를 잘못 사용하고 있습니다. 이를 바탕으로

난에 자바 코드를 변경 :이 dababase 부하가 13 %로 평균 70 %에서 떨어진 후

ResultSet rs = null;  
Statement stmt = null; 
Connection conn = null; 
Integer myId=null; 
String myVeryUniqueFileName = strFromSomeWhere; 
try 
{ 
    conn = Database.getConnection(); 
    stmt = conn.createStatement() 
    // 
    rs = stmt.executeQuery("SELECT id FROM mytable WHERE filename = '" 
         + myVeryUniqueFileName + "'"); 
    if (rs.next()) 
    { 
    myId= new Integer(rs.getInt(1)); 
    }    
    if (rs.next()) 
    { 
    throw new DBException("Duplicate myId: " + myId); 
    } 
    return myId; 
} catch (Exception e) { 
    // handle this 
} 

0

설명하는 현상은 주로 잘못 캐시 된 쿼리 계획 때문에 발생합니다.

색인을 다시 작성하거나 통계를 업데이트하십시오.

+0

쿼리 계획이 인덱스 다시 작성과 직접적으로 관련이 있다고 말할 수 없습니다. 그게 당신이 암시하는 것 같아요. –

0

성명은 아마도 준비된 진술이 아닌 사용하고 있습니다. 쿼리 최적화 프로그램이 매번 작업해야하므로 문을 미리 컴파일하고 캐시하지 않습니다. 준비된 명령문을 사용하면 쿼리를 실행하는 가장 좋은 방법을 찾게 될 것이고 저장하게됩니다. 다음 번에 그것을 사용하면 시험을 치르지 않고 결과를 얻는 좋은 방법을 찾아 낼 것입니다. 이미 수행 한 계획입니다.

1

이 쿼리를 실행하고 결과를 검색하는 Java 코드를 게시 할 수 있습니까? 에 상당한 시간이 걸릴 표시에 자바 코드를 일으키는

가능한 요인은 다음과 같습니다

  1. 조회에 많은 수의 레코드를 반환하고 쿼리 브라우저 것 만 표시하는 반면 자바에 그들 모두를 검색하려는 첫 번째 100 (그 숫자가 무엇이든) 요구에 따라 다른 것을로드하십시오.
  2. 서로 다른 시간대를 비교하고 있습니다. 예를 들어 쿼리 브라우저에서 "query took X ms"가 표시되면 Java가 연결을 종료 할 때까지 연결을 기다리게됩니다.
  3. 개체 (결과 보유)는 비용이 많이 들거나 채워지는 장면 뒤에서 일부 처리를 수행 중일 수 있습니다.
1

특히 MSSQL 2005에서는 말할 수 없지만 바인드 변수를 사용하는 준비된 명령문과 값이 포함 된 동등한 명령문 사이에는 실행 계획이 다를 수 있습니다.

이 이론을 테스트하려면 바인드 매개 변수를 삭제하고 Java에서 SQL 쿼리를 실제 파일 이름 (따옴표)과 연결하십시오. 이렇게하면 사과와 사과를 비교할 수 있습니다.

또한 발생하는 CPU 시간의 차이를 나타내는 데 유용합니다.그것은 몇 가지 규모 또는 100 % 미만입니까?

관련 문제