2012-03-18 3 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)); 

입니다 이 호출에서 생성 된 두 개의 SQL이고 nhibernate 프로파일 러는 "DIfferent 매개 변수 크기로 인해 비효율적 인 쿼리 계획 캐시가 발생합니다 나이 "

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

오라클 질의 계획은 어떻게 지금은 의존하지 않지만 [시나리오에 대한 ayende의 설명에서 지적한 시나리오] (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에서 상속) : 나는 이것을 테스트

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

당신이 유창함 NHibernate에 당신이이 같은 드라이버 구현을 등록 사용하는 경우

오버 라이트 된 OracleClientDriver (ODP.NET이 아닌 기존 Microsoft 오라클 드라이버 사용), mattk의 응답 코드와 비슷하지만 문자열 매개 변수의 크기가 같았지만 Oracle 실행의 차이점은 없었습니다.

Here's 내 게시물을 Stackexchange DBA.

Oracle Enterprise Manager는 내 NHibernate에서 생성 된 SQL에 대해 중복 쿼리를 표시하지 않았으며 두 버전 모두 각 호출은 구문 분석 (긴 테스트에서는 약 1000 개까지)을 발생 시켰지만 변수와 고정 사이에는 차이가 거의 없었습니다 매개 변수 길이.

실제로 Oracle은 바인드 매개 변수가없는 쿼리에 대해서만 중복 쿼리 계획을 만들었지 만 SQL 문자열에 연결된 값 (코딩 된 SQL에서는 피할 수있는 항목)이 있습니다. 이제 쿼리 계획 (또는 오라클 용어로 커서 공유)을 재사용 할 때 Oracle의 매개 변수 크기는 중요하지 않습니다.

SQL은 계획 일치에 대한 SQL 문자열 만 비교하며 SQL Server는 매개 변수 정의도 검사합니다. 동적 SQL을 볼 때 당신은 또한 가 IMMEDIATE (오라클) 및 sp_executesql을 (SQL 서버)을 실행 명령 차이를 볼 수 있습니다 을 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 요청이 데이터베이스로 전송되어야하며 응용 프로그램은 prepared statement에 대한 핸들을 유지해야합니다 하나의 연결에만 사용할 수 있습니다. 의미 : 새로운 핸들을 자주 만들어야합니다. 오라클과 ODP.NET으로 테스트했을 때, 핸들 자체로 질의하는 것은 문자열 평등에 의해 데이터베이스와 일치하는 매개 변수화 된 SQL보다 성능이 약간 더 높지만 준비되지 않은 버전보다 다소 느립니다. 같은 DB 연결이나 NHibernate 세션에서 동일한 쿼리를 여러 번 사용하는 경우 Prepare가 좋습니다.