2017-11-26 4 views
2

데이터에 액세스하는 Grails 애플리케이션에 이상한 문제가 있습니다. 더 자세히 설명 드리면 PreparedStatement.executeQuery 대 Statement.executeQuery를 사용하여 일반 java8 소규모 애플리케이션으로 문제를 격리했습니다.preparedQuery가 아니라 preparedStatement를 사용한 쿼리가 느림

    
    // executes in milliseconds     
    directSql = "select top(10) * from vdocuments where codcli = 'CCCC' and    serial = 'SSSS' ORDER BY otherField DESC;"; 
    stmt = con.createStatement(); 
    rs = stmt.executeQuery(directSql); 


    // More than 10 minutes 
    sqlPrepared = "select top(10) * from vdocuments where codCli = ? and serial = ? ORDER BY otherField DESC;"; 
    PreparedStatement pStatement = con.prepareStatement(sqlPrepared); 
    pStatement.setString(1, "CCCC"); 
    pStatement.setString(2, "SSSS"); 
    rsPrepared = pStatement.executeQuery(); 

같은 쿼리 :

코드의 다음 코드를 생각해 보자.

데이터는 SqlServer에서 볼 수 있습니다 (2008 년 생각합니다. 지금은 액세스 할 수 없습니다). 1500 만 개가 넘는 레코드가있는 테이블에서 가져온 데이터입니다. 필요한 모든 필드에 대한 인덱스가 있으며 콘솔에서 실행되는 동일한 쿼리 (첫 번째 쿼리)도 매우 빠르게 실행됩니다.

ORDER 절없이 느린 PreparedStatement 쿼리를 실행하면 빠르게 실행됩니다.

데이터베이스에 어떤 이유로 든 인덱스를 사용하지 않고 preparedStatement를 사용할 때 전체 검사를 수행하는 것이 확실하지만 어쩌면 틀 렸습니다. 그래서 어떤 생각이든 열려 있습니다.

아마 드라이버 (sqlserver 공식 최신 및 jtds 테스트되었습니다) 연결에서 모든 종류의 EOF 기다리는 데이터를 보유하고 있지만 내 측면에 tcpdump 함께 확인한 및 데이터가 수신 된 것 같아요.

왜 이런 일이 발생하는지 알 수 없으므로 어떤 아이디어라도 환영 할 것입니다.

고맙습니다!

+0

성능 문제가있는 경우 가장 먼저 제안하는 것은 실행 계획을 검토하는 것입니다. –

+0

나는 그것을 시도 할 것이지만, 두 경우 모두 왜 달라야 하는가? 그리고 최악의 경우, 어떻게 준비된 스테이트먼트를 위해 그것을합니까? 나는 자바에서 _EXPLAIN PLAN ... _ 내가 아는 한 실행할 수 없다. 감사합니다. –

+0

데이터 형식이 일치하지 않거나 매개 변수 스니핑으로 인해 계획이 다를 수 있습니다. 실행 계획에서이를 나타낼 수 있지만 공통적 인 문제는 유니 코드 문자열 매개 변수를 인덱스가 효율적으로 사용되지 못하도록하는 varchar 열과 비교한다는 것입니다. 또는 캐시 된 계획이 재사용되는 매개 변수 스니핑으로 인해 현재 매개 변수 값에 대해 최적이 아닐 수 있습니다. –

답변

0

필자의 경우 적어도 마침내 해결책을 찾았습니다. 내가 여기에있어 http://mehmoodbluffs.blogspot.com.es/2015/03/hibernate-queries-are-slow-sql-servers.html. 유니 코드로 매개 변수를 보내지 않는 (드라이버? sqlServer?) 문제가 해결되었습니다.

String connectionUrl = "jdbc:sqlserver://server:port;databaseName=myDataBase;sendStringParametersAsUnicode=false"; 

이제 직접 쿼리 모두와자는 PreparedStatements 밀리 초 속도로 실행 :

현재 연결 문자열은 지금입니다.

@DanGuzman에게 감사드립니다.