2011-10-07 2 views
3

주어진 시간 범위 내에서 레코드를 선택하는 쿼리에 문제가 있습니다.NHibernate 및 DateTime 맵핑 문제

내가 선택한 열은 DATE 유형입니다. 이 열을 DateTime 속성으로 매핑했는데 쿼리가 작동하지만 느립니다.

생성 된 쿼리는 다음과 같습니다

select kifkalende0_.KALENDER_MEDARBEJDER_ID as KALENDER1_119_0_, 
    kifkalende1_.KALENDER_EMNE_ID  as KALENDER1_210_1_, 
    kifkalende0_.OPDATERET_TIDSPUNKT  as OPDATERET2_119_0_, 
    kifkalende0_.AENDRET     as AENDRET119_0_, 
    kifkalende0_.OPDATERET_AF   as OPDATERET4_119_0_, 
    kifkalende0_.OPRETTET_AF    as OPRETTET5_119_0_, 
    kifkalende0_.OPRETTET_TIDSPUNKT  as OPRETTET6_119_0_, 
    kifkalende0_.SLETTET     as SLETTET119_0_, 
    kifkalende0_.KALENDER_EMNE_ID  as KALENDER8_119_0_, 
    kifkalende0_.MEDARBEJDER_ID   as MEDARBEJ9_119_0_, 
    kifkalende1_.OPDATERET_TIDSPUNKT  as OPDATERET2_210_1_, 
    kifkalende1_.BESKRIVELSE    as BESKRIVE3_210_1_, 
    kifkalende1_.DATO     as DATO210_1_, 
    kifkalende1_.ER_FRA_SAG    as ER5_210_1_, 
    kifkalende1_.FRA_SAG_ID    as FRA6_210_1_, 
    kifkalende1_.FRA_TABEL    as FRA7_210_1_, 
    kifkalende1_.FRA_TID     as FRA8_210_1_, 
    kifkalende1_.OPDATERET_AF   as OPDATERET9_210_1_, 
    kifkalende1_.OPRETTET_AF    as OPRETTET10_210_1_, 
    kifkalende1_.OPRETTET_TIDSPUNKT  as OPRETTET11_210_1_, 
    kifkalende1_.SAG_TYPE    as SAG12_210_1_, 
    kifkalende1_.TIL_TID     as TIL13_210_1_, 
    kifkalende1_.YDERLIGERE_BESKRIVELSE as YDERLIGERE14_210_1_, 
    kifkalende1_.EMNE_ID     as EMNE15_210_1_, 
    kifkalende1_.PERSON_ID    as PERSON16_210_1_ 
from "KIF_KALENDER_MEDARBEJDER" kifkalende0_ 
    left outer join "KIF_KALENDER_EMNE" kifkalende1_ on 
kifkalende0_.KALENDER_EMNE_ID = kifkalende1_.KALENDER_EMNE_ID, 
    "KIF_KALENDER_EMNE" kifkalende2_ 
where kifkalende0_.KALENDER_EMNE_ID = kifkalende2_.KALENDER_EMNE_ID 
    and (kifkalende0_.MEDARBEJDER_ID in (7624 /* :p3 */,6226 
/* :p4 */,7382 /* :p5 */,5774 /* :p6 */, 5775 /* :p7 */,8259 
/* :p8 */,8218 /* :p9 */,9899 /* :p10 */, 6000 /* :p11 */,5779 
/* :p12 */,5780 /* :p13 */,5782 /* :p14 */, 5783 /* :p15 */,5784 
/* :p16 */,5785 /* :p17 */,5788 /* :p18 */, 5789 /* :p19 */,5790 
/* :p20 */,7341 /* :p21 */,8963 /* :p22 */, 10201 /* :p23 */,10388 
/* :p24 */))  
and kifkalende2_.DATO >= TIMESTAMP '2010-11-10 00:00:00.00' /* :p0 */ 
and kifkalende2_.DATO <= TIMESTAMP '2010-11-10 23:59:59.00' /* :p1 */ 
and (kifkalende0_.SLETTET = TIMESTAMP '1899-12-31 00:00:00.00' /* :p2 */ 
    or kifkalende0_.SLETTET is null); 

그리고 우리의 데이터베이스에

, 그것을 실행하기 위해 1500 MS 주위 소요 ( NHProfiler에 의해 제공). 우리가 수동으로 쿼리를 변경하는 경우

는 :

select kifkalende0_.KALENDER_MEDARBEJDER_ID as KALENDER1_119_0_, 
    kifkalende1_.KALENDER_EMNE_ID  as KALENDER1_210_1_, 
    kifkalende0_.OPDATERET_TIDSPUNKT  as OPDATERET2_119_0_, 
    kifkalende0_.AENDRET     as AENDRET119_0_, 
    kifkalende0_.OPDATERET_AF   as OPDATERET4_119_0_, 
    kifkalende0_.OPRETTET_AF    as OPRETTET5_119_0_, 
    kifkalende0_.OPRETTET_TIDSPUNKT  as OPRETTET6_119_0_, 
    kifkalende0_.SLETTET     as SLETTET119_0_, 
    kifkalende0_.KALENDER_EMNE_ID  as KALENDER8_119_0_, 
    kifkalende0_.MEDARBEJDER_ID   as MEDARBEJ9_119_0_, 
    kifkalende1_.OPDATERET_TIDSPUNKT  as OPDATERET2_210_1_, 
    kifkalende1_.BESKRIVELSE    as BESKRIVE3_210_1_, 
    kifkalende1_.DATO     as DATO210_1_, 
    kifkalende1_.ER_FRA_SAG    as ER5_210_1_, 
    kifkalende1_.FRA_SAG_ID    as FRA6_210_1_, 
    kifkalende1_.FRA_TABEL    as FRA7_210_1_, 
    kifkalende1_.FRA_TID     as FRA8_210_1_, 
    kifkalende1_.OPDATERET_AF   as OPDATERET9_210_1_, 
    kifkalende1_.OPRETTET_AF    as OPRETTET10_210_1_, 
    kifkalende1_.OPRETTET_TIDSPUNKT  as OPRETTET11_210_1_, 
    kifkalende1_.SAG_TYPE    as SAG12_210_1_, 
    kifkalende1_.TIL_TID     as TIL13_210_1_, 
    kifkalende1_.YDERLIGERE_BESKRIVELSE as YDERLIGERE14_210_1_, 
    kifkalende1_.EMNE_ID     as EMNE15_210_1_, 
    kifkalende1_.PERSON_ID    as PERSON16_210_1_ 
from "KIF_KALENDER_MEDARBEJDER" kifkalende0_ 
    left outer join "KIF_KALENDER_EMNE" kifkalende1_ on 
kifkalende0_.KALENDER_EMNE_ID = kifkalende1_.KALENDER_EMNE_ID, 
    "KIF_KALENDER_EMNE" kifkalende2_ 
where kifkalende0_.KALENDER_EMNE_ID = kifkalende2_.KALENDER_EMNE_ID 
    and (kifkalende0_.MEDARBEJDER_ID in (7624 /* :p3 */,6226 
/* :p4 */,7382 /* :p5 */,5774 /* :p6 */, 5775 /* :p7 */,8259 
/* :p8 */,8218 /* :p9 */,9899 /* :p10 */, 6000 /* :p11 */,5779 
/* :p12 */,5780 /* :p13 */,5782 /* :p14 */, 5783 /* :p15 */,5784 
/* :p16 */,5785 /* :p17 */,5788 /* :p18 */, 5789 /* :p19 */,5790 
/* :p20 */,7341 /* :p21 */,8963 /* :p22 */, 10201 /* :p23 */,10388 
/* :p24 */)) 
    and kifkalende2_.DATO>=to_date('10-11-2010 00:00:00', 'DD-MM-YYYY HH24:MI:SS') 
    and kifkalende2_.DATO<=to_date('10-11-2010 23:59:59', 'DD-MM-YYYY HH24:MI:SS') 
    and (kifkalende0_.SLETTET=to_date('31-12-1899 00:00:00', 'DD-MM-YYYY HH24:MI:SS') 
    or kifkalende0_.SLETTET is null); 

은 약 50ms로 실행됩니다.

NHibernate가 날짜 비교를 위해 타임 스탬프 대신 to_date를 생성하도록하는 방법은 무엇입니까 ??

나는 RegisterDateTimeTypeMappings가 Oracle10gDialect에서 작동하는 방법에 관해서는 조금 혼란 스러워요,하지만 난

  protected override void RegisterDateTimeTypeMappings() 
      { 
        RegisterColumnType(DbType.Date, "DATE"); 
        //RegisterColumnType(DbType.DateTime, "TIMESTAMP(4)"); 
        RegisterColumnType(DbType.DateTime, "DATE"); 
        RegisterColumnType(DbType.Time, "TIMESTAMP(4)"); 
      } 

에 방법을 변경, 그것을 확장하려하지만 도움이되지 않았다.

우리의 환경은 다음과 같습니다

  • .NET (C#을) 오라클 11g
에 대해 ODP.Net 11.2.2.0
  • Linq에
  • 을 통해 주로 사용 4.0
  • 자 NHibernate 3.1.0,

    누구에게 어떤 제안이 있습니까?

    덕분에, ./Daniel

  • 답변

    6

    다음 NHibernate 클래스를 재정 의하여 내 문제를 해결했습니다. NHProfiler는 여전히 TIMESTAMP 값을 표시하지만 기본 매개 변수는 DATE 유형입니다. 이는 oracle 열도 DateTime 인 경우 인덱싱 할 수 있습니다. NHProfiler의 매개 변수 위로 마우스를 가져 가면 : p0 : TIMESTAMP - '2011-07-01 00 : 00 : 00.00'과 같은 내용을 볼 수 있습니다. 대신 : p0 : TIMESTAMP - '2011-07 -01 00 : 00 : 00.00 '시간 소인.

    저는 Oracle 11g, C# .Net 4, Nhibernate 3.2도 사용하고 있습니다.

    public class OracleDataClientDriver2 : OracleDataClientDriver 
    { 
        protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType) 
        { 
         switch (sqlType.DbType) 
         { 
           //Timestamp columns not indexed by Oracle 11g date columns. - Use Date 
          case DbType.DateTime: 
           base.InitializeParameter(dbParam, name, SqlTypeFactory.Date); 
           break; 
          default: 
           base.InitializeParameter(dbParam, name, sqlType); 
           break; 
         } 
        } 
    } 
    
    -1

    는 매개 변수가 올바른 유형의있는 모든 경우 어떤 변환이 없어야한다. TIMESTAMP 또는 to_date()는 문자열 형식의 타임 스탬프가있는 경우에만 필요합니다. 매개 변수가 올바르게 입력되어있는 경우는 다음과 같이 읽어야

    select 
         tab.COL as col 
        from 
         TABLE tab 
        where 
         tab.COL = :p0; 
    :p0 = 01.01.2000 00:00:00 [Type: DateTime (0)] 
    

    그래서 쿼리에 DateTime 객체를 전달하고 있는지 확인하십시오.

    +0

    내 쿼리 및 매핑에서 DateTime 개체입니다. 내가 게시 한 SQL은 오라클이받은 SQL입니다. NHibernate 또는 ODP.NET은 .net과 SQL 간의 변환을 처리합니다. – dajoni

    +0

    @Djn NHProf 출력 대신 NHibernate에서 직접 오는 SQL 출력 (NHibernate.SQL 로거 또는 콘솔 출력을 통해)을 확인하십시오. 내가 게시 한 것과 같아야합니다. – cremor

    +0

    사실, 내 쿼리는 매개 변수 이름에 .net 유형이 추가 된 것처럼 보입니다. 왜 그렇게 느린지 이해할 수 없기 때문에 NHprofiler를 사용하여 구문 분석 된 SQL을 구했습니다. 내가 가진 상황은 [this]와 조금 비슷하게 보입니다 (http://stackoverflow.com/questions/2464502/avoid-implicit-conversion-from-date-to-timestamp-for-selects-with-oracle-using-hi) 그러나 나는 우리 환경에 대한 제안을 일치시킬 수 없다. – dajoni