2012-03-18 6 views
6

NHibernateのプロファイラは、クエリプランに関するエラーメッセージの多くを示しています。異なるパラメータサイズは非効率的なクエリプランのキャッシュになり

異なるパラメータサイズは非効率的なクエリプランのキャッシュの使用状況で結果をまたにあなたを導き

http://nhprof.com/Learn/Alerts/UncachedQueryPlanで説明し、セッションを構築するときにprepare_sql = trueパラメータの使用について警告します。私は流暢にそのように:

しかし、それはエラーメッセージがまだそこにあるように動作していないようです。これはOracleClientConfigurationの制限ですか、それとも間違っていますか?

編集これについていくつかのより多くの情報を提供するために...私のリポジトリで

私はこの

session.Query<TEntity>.Where(predicate).ToList(); 

行うと、これは、例えばそれらのためにコール

var value = ParameterRepository.First(p => (p.Pipeline.Id == pipelineId && p.Name == name)); 

ですこの呼び出しから生成された2つのSQLであり、nhibernateプロファイラは「DIEFerentパラメータサイズが非効率なクエリプランのキャッシュをもたらす年齢」

select GUID1_12_, 
     PARAMETER2_12_, 
     PARAMETER3_12_, 
     GUID4_12_ 
from (select pipelineex0_.GUID_PIPELINE_EXEC_PARAMETER as GUID1_12_, 
       pipelineex0_.PARAMETER_NAME    as PARAMETER2_12_, 
       pipelineex0_.PARAMETER_VALUE    as PARAMETER3_12_, 
       pipelineex0_.GUID_PIPELINE_TRACKING  as GUID4_12_ 
     from FCT_PIPELINE_EXEC_PARAMETER pipelineex0_ 
     where pipelineex0_.GUID_PIPELINE_TRACKING = 'A5916E73CF1E406DA26F65C24BFBF694' /* :p0 */ 
       and pipelineex0_.PARAMETER_NAME = 'lid' /* :p1 */) 
where rownum <= 1 /* :p2 */ 

と第二

select GUID1_12_, 
     PARAMETER2_12_, 
     PARAMETER3_12_, 
     GUID4_12_ 
from (select pipelineex0_.GUID_PIPELINE_EXEC_PARAMETER as GUID1_12_, 
       pipelineex0_.PARAMETER_NAME    as PARAMETER2_12_, 
       pipelineex0_.PARAMETER_VALUE    as PARAMETER3_12_, 
       pipelineex0_.GUID_PIPELINE_TRACKING  as GUID4_12_ 
     from FCT_PIPELINE_EXEC_PARAMETER pipelineex0_ 
     where pipelineex0_.GUID_PIPELINE_TRACKING = 'A5916E73CF1E406DA26F65C24BFBF694' /* :p0 */ 
       and pipelineex0_.PARAMETER_NAME = 'period' /* :p1 */) 
where rownum <= 1 /* :p2 */ 

私見では 『蓋』と別のクエリ・プランを生成している 『期間』がこのPARAMETER_NAMEです。予め

+0

異なるOracle実行計画は何ですか? – steve

+0

Oracleの問合せ計画はどのようになっているのですか。しかし、このシナリオは[問題の説明に指摘されている](http://nhprof.com/Learn/Alerts/UncachedQueryPlan)と非常によく似ています。簡単に言えば、nhibernateは、親しみやすいクエリプランでクエリーを実行するために、そして、私がうまく動作しないことからクエリーを実行するように確信しなければならないと言います。 – guillem

+0

まあ、私はより分析的なアプローチをお勧めします、そうでなければ試行錯誤です。エラーは何ですか? – steve

答えて

0

おかげ同じ平面にパラメータがパラメータ値に関係なく、同じ長さに設定する必要があるたびを生成します。

ドライバ実装をカスタマイズして、クエリパラメータの長さをマッピングで指定されたフィールド長に設定できます。

public class CustomOracleClientDriver : OracleClientDriver 
{ 
    protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType) 
    { 
     base.InitializeParameter(dbParam, name, sqlType); 

     if (sqlType.LengthDefined) 
      dbParam.Size = sqlType.Length; 
    } 
} 

(注:ODP.Netを使用している場合OracleDataClientDriverから継承)

あなたが流暢NHibernateはを使用している場合は、このようなあなたのドライバの実装を登録します。

Fluently.Configure() 
       .Database(
        OracleDataClientConfiguration.Oracle10 
         .ConnectionString(c => c.FromAppSetting("ConnectionString")) 
         .Driver<CustomOracleClientDriver>()) 
0

私はこれをテスト(ODP.NETではなく、古いMicrosoftのOracleドライバを使用して)オーバーライドされたOracleClientDriverを使用しました。文字列パラメータのサイズは現在共通ですが、mattkの回答のコードと似ています。

Here's私のPostはStackexchange DBAです。

Oracle Enterprise Managerでは、NHibernateで生成されたSQLに対して重複した問合せは表示されませんでしたが、どちらのコールでも構文解析が発生しました(長いテストでは1000まで)パラメータの長さ。

実際、Oracleはバインド・パラメータのない問合せに対してのみ、重複する問合せプランを作成しましたが、SQL文字列に連結された値(コード化されたSQLでは回避するもの)があります。だから、今では、クエリ・プランを再利用する場合(Oracleの場合、カーソルの共有)には、パラメータ・サイズはOracleにとって重要ではないようです。

SQLはプランの照合にSQL文字列を比較するだけで、SQL Serverはパラメータ定義もチェックします。動的SQLを見ているときにも、違いを見ることができはIMMEDIATE(オラクル)とsp_executesqlを(SQL Serverを)EXECUTEコマンド:sp_executesqlをも(文字列では、ないのためのパラメータとしてパラメータ定義と文字列を取得sp_executesqlが呼び出されます)。私はNHibernate/ADO.NETがsp_executesqlをSQL Serverにパラメータ化されたクエリを送信するときに使用することを知っているので、SQL Serverでは処理が異なる可能性があります。また、NHibernateを介してSQL Serverに接続する場合、すべての文字列パラメータはNHibernateマッピングまたはデフォルトの最大長からのユニークなサイズを持つため、関連する場所で問題が修正されている可能性があります。私が間違っているなら私を訂正してください!

ADO.NET/NHibernateでPrepare/prepare_sqlを使用すると、実装によっては、SQLが実行される前にPrepareリクエストをデータベースに送信する必要があります。アプリケーションはPreparedStatementのハンドルを保持する必要があります1つの接続に対してのみ使用できます。意味:新しいハンドルを頻繁に作成する必要があります。私はOracleとODP.NETでテストしたところ、準備されていないバージョンよりもやや遅かったですが、ハンドル自体のクエリは、文字列の等価性によってデータベース上で照合されたパラメータ化されたSQLによるパフォーマンスよりもパフォーマンスはほんのわずかです。アプリケーションが同じDB接続またはNHibernateセッション内で何度も同じクエリを使用する場合は、Prepareが良いと思われます。

関連する問題