2017-11-26 13 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

私はそれを試してみるつもりですが、なぜ両方の場合に違いがありますか?そして最悪の場合、私はpreparedStatementのためにそれをどうやって行うのですか?私はJavaから_EXPLAIN PLAN ... _私が知る限り実行できません。 ありがとうございます! –

+0

データタイプの不一致またはパラメータのスニッフィングのために、計画が異なる可能性があります。実行計画ではこれが明らかになりますが、一般的な問題は、Unicode文字列パラメータを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"; 

そして今、両方の直接のクエリとのPreparedStatementは、ミリ秒の速度で動作します。

@DanGuzmanありがとうございました!

関連する問題