不同的参数大小会导致查询计划缓存效率低下

gui*_*lem 6 oracle nhibernate fluent-nhibernate sql-execution-plan

Nhibernate探查器显示有关查询计划的大量错误消息:

不同的参数大小会导致查询计划缓存使用效率低下

它还会引导您在http://nhprof.com/Learn/Alerts/UncachedQueryPlan中进行解释,并prepare_sql = true在构建会话时警告您使用参数.我这样做是流利的:

.ExposeConfiguration(configuration => configuration
    .SetProperty("current_session_context_class", "thread_static")
    .SetProperty("prepare_sql", "true")
    .SetProperty("generate_statistics", "true")
    )
Run Code Online (Sandbox Code Playgroud)

但似乎它没有工作,因为错误消息仍然存在.这是对OracleClientConfiguration的限制还是我做错了?

编辑提供有关此内容的更多信息......

在我的存储库中,我这样做

session.Query<TEntity>.Where(predicate).ToList();
Run Code Online (Sandbox Code Playgroud)

这就是电话

var value = ParameterRepository.First(p => (p.Pipeline.Id == pipelineId && p.Name == name));
Run Code Online (Sandbox Code Playgroud)

例如,这些是从此调用生成的两个SQL,并且nhibernate profiler显示为"不同的参数大小导致查询计划缓存使用效率低下"

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 */
Run Code Online (Sandbox Code Playgroud)

第二个

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 */
Run Code Online (Sandbox Code Playgroud)

恕我直言,这个PARAMETER_NAME带有'lid'和'period',生成不同的查询计划.

提前致谢

mat*_*ttk 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

(注意:如果您使用 ODP.Net,请从 OracleDataClientDriver 继承)

如果您使用 Fluent NHibernate,您可以像这样注册驱动程序实现:

Fluently.Configure()
                .Database(
                    OracleDataClientConfiguration.Oracle10
                        .ConnectionString(c => c.FromAppSetting("ConnectionString"))
                        .Driver<CustomOracleClientDriver>())
Run Code Online (Sandbox Code Playgroud)