2011-11-18 2 views
3

내가이 모든 게으른 로딩을 중지하고 열망 로딩을 조인 할 필요가 위에 나는 이러한 쿼리 사례에nhibernate에서 ToFuture를 사용하는 방법?

// Linq 
    var allRecords = session.Query<Table1P>().FetchMany(x => x.Table2).FetchMany(x => x.Table3).FetchMany(x => x.Table4).FetchMany(x => x.Table6).ToList(); 

// Hql 
string hqlQuery = @"from Table1 tbl1 
           left join fetch tbl1.Table2 tbl2 
           left join fetch tbl1.Table3 
           left join fetch tbl1.Table4 
           left join fetch tbl1.Table6 
           left join fetch tbl2.Table5s"; 

을 말해봐. 이제 이것은 nhibernate 프로파일 러에 너무 많은 조인에 대한 경고를 생성합니다.

http://nhprof.com/Learn/Alerts/TooManyJoins

그래서이 경고를 중지하는 한 가지 방법은 조인 헤어입니다. 여러 쿼리를 수행 할 수 있습니다. 이것이 내가하려는 일이다. 그러나 동시에 나는 (내가 너무 많은 조인을 멈추기 위해) 질의를 해칠 수 있다고 생각하는 미래의 기능에 대해 읽었지만 한 번에 그것을 실행한다.

편집 내가 ToFuture을 시도하고 돌아올 데이터의 양을 제한하려고 할 때 느린 그것을 발견 된

(나는 그때 그것을 빨리 충돌하지 않는 한 모든 것을 얻으려고하는 경우) . NHibernate에 프로파일 러에서 촬영

// result (4.808 seconds), row count 6944/75/ 374, duration 1ms/4022 ms 

       // will load the Entities with Table2 fetched 
       var allRecords = session.Query<Table1P>() 
        .FetchMany(x => x.Table2) 
        .ToFuture() 
        .Take(3000); 

       // will load the Entities with Table3 fetched 
       session.Query<Table1P>() 
        .FetchMany(x => x.Table3) 
        .ToFuture(); 

       // will load the Entities with Table4 fetched 
       session.Query<Table1P>() 
        .FetchMany(x => x.Table4) 
        .ToFuture(); 

       // will load the Entities with Table6 fetched 
       session.Query<Table1P>() 
        .FetchMany(x => x.Table6) 
        .ToFuture(); 

       // will trigger all queries at once and the session cache will make sure, 
       // that the results of all queries fill the same Entities 
       allRecords.ToList(); 


select table1p0_.Id  as Id1_0_, 
     table2x1_.Id  as Id2_1_, 
     table1p0_.F1  as F2_1_0_, 
     table1p0_.F2  as F3_1_0_, 
     table1p0_.F3  as F4_1_0_, 
     table2x1_.F1  as F2_2_1_, 
     table2x1_.F2  as F3_2_1_, 
     table2x1_.F3  as F4_2_1_, 
     table2x1_.Table1_id as Table5_2_1_, 
     table2x1_.Table1_id as Table5_0__, 
     table2x1_.Id  as Id0__ 
from Table1 table1p0_ 
     left outer join [Table2] table2x1_ 
     on table1p0_.Id = table2x1_.Table1_id; 



select table1p0_.Id  as Id1_0_, 
     table3x1_.Id  as Id3_1_, 
     table1p0_.F1  as F2_1_0_, 
     table1p0_.F2  as F3_1_0_, 
     table1p0_.F3  as F4_1_0_, 
     table3x1_.F1  as F2_3_1_, 
     table3x1_.F2  as F3_3_1_, 
     table3x1_.F3  as F4_3_1_, 
     table3x1_.Table1_id as Table5_3_1_, 
     table3x1_.Table1_id as Table5_0__, 
     table3x1_.Id  as Id0__ 
from Table1 table1p0_ 
     left outer join [Table3] table3x1_ 
     on table1p0_.Id = table3x1_.Table1_id; 



select table1p0_.Id  as Id1_0_, 
     table4x1_.Id  as Id4_1_, 
     table1p0_.F1  as F2_1_0_, 
     table1p0_.F2  as F3_1_0_, 
     table1p0_.F3  as F4_1_0_, 
     table4x1_.F1  as F2_4_1_, 
     table4x1_.F2  as F3_4_1_, 
     table4x1_.F3  as F4_4_1_, 
     table4x1_.Table1_id as Table5_4_1_, 
     table4x1_.Table1_id as Table5_0__, 
     table4x1_.Id  as Id0__ 
from Table1 table1p0_ 
     left outer join [Table4] table4x1_ 
     on table1p0_.Id = table4x1_.Table1_id; 



select table1p0_.Id  as Id1_0_, 
     table6x1_.Id  as Id6_1_, 
     table1p0_.F1  as F2_1_0_, 
     table1p0_.F2  as F3_1_0_, 
     table1p0_.F3  as F4_1_0_, 
     table6x1_.F1  as F2_6_1_, 
     table6x1_.F2  as F3_6_1_, 
     table6x1_.F3  as F4_6_1_, 
     table6x1_.Table1_id as Table5_6_1_, 
     table6x1_.Table1_id as Table5_0__, 
     table6x1_.Id  as Id0__ 
from Table1 table1p0_ 
     left outer join [Table6] table6x1_ 
     on table1p0_.Id = table6x1_.Table1_id; 

쿼리와 시간 ToFuture 사용

var allRecords = session.Query<Table1P>().FetchMany(x => x.Table2).FetchMany(x => x.Table3).FetchMany(x => x.Table4).FetchMany(x => x.Table6).Take(3000).ToList(); 

// result (2.731 seconds), row count 3000, duration 8 ms/ 2013 ms 

select TOP (3000 /* @p0 */) table1p0_.Id  as Id1_0_, 
       table2x1_.Id  as Id2_1_, 
       table3x2_.Id  as Id3_2_, 
       table4x3_.Id  as Id4_3_, 
       table6x4_.Id  as Id6_4_, 
       table1p0_.F1  as F2_1_0_, 
       table1p0_.F2  as F3_1_0_, 
       table1p0_.F3  as F4_1_0_, 
       table2x1_.F1  as F2_2_1_, 
       table2x1_.F2  as F3_2_1_, 
       table2x1_.F3  as F4_2_1_, 
       table2x1_.Table1_id as Table5_2_1_, 
       table2x1_.Table1_id as Table5_0__, 
       table2x1_.Id  as Id0__, 
       table3x2_.F1  as F2_3_2_, 
       table3x2_.F2  as F3_3_2_, 
       table3x2_.F3  as F4_3_2_, 
       table3x2_.Table1_id as Table5_3_2_, 
       table3x2_.Table1_id as Table5_1__, 
       table3x2_.Id  as Id1__, 
       table4x3_.F1  as F2_4_3_, 
       table4x3_.F2  as F3_4_3_, 
       table4x3_.F3  as F4_4_3_, 
       table4x3_.Table1_id as Table5_4_3_, 
       table4x3_.Table1_id as Table5_2__, 
       table4x3_.Id  as Id2__, 
       table6x4_.F1  as F2_6_4_, 
       table6x4_.F2  as F3_6_4_, 
       table6x4_.F3  as F4_6_4_, 
       table6x4_.Table1_id as Table5_6_4_, 
       table6x4_.Table1_id as Table5_3__, 
       table6x4_.Id  as Id3__ 
from Table1 table1p0_ 
     left outer join [Table2] table2x1_ 
     on table1p0_.Id = table2x1_.Table1_id 
     left outer join [Table3] table3x2_ 
     on table1p0_.Id = table3x2_.Table1_id 
     left outer join [Table4] table4x3_ 
     on table1p0_.Id = table4x3_.Table1_id 
     left outer join [Table6] table6x4_ 
     on table1p0_.Id = table6x4_.Table1_id 

. 테스트는 코드 집합 중 하나를 사용하여 한 번 실행하여 결과를 기록하고 .net 개발 서버를 중지 한 다음 다른 코드 집합을 실행하여 실행되었습니다.

표 - 6200 행 표 2 - 744 행 표 3 - 75 행 표 4 - 374 행 표 6 - 300 행

거의 표 1은 모든 다른 테이블에 많은 일이있다.

+0

'.Take (3000)'은'TOP (3000)' –

+0

Ah로 쿼리에 적용되기를 원하면'.ToFuture()'앞에 와야합니다. 이제 행 수가 3021/3998/374/300이되었습니다. 지속 시간 35ms/4825, 총 5.703 초. 한 번에 모든 작업을 수행하면 총 3.33 개로 2ms/2307ms의 지속 시간으로 3000 개의 행이 생성됩니다. ToFuture()가 같은 양을 얻으려면 더 많은 행을 반환해야하며 느리다는 것처럼 보입니다. 그게 단지 그것이 맞는지 또는 내가 여전히 잘못하고있는 것인지 확실하지 않습니다. – chobo2

답변

2
// will load the Entities with Table2 fetched 
var allRecords = session.Query<Table1P>() 
    .FetchMany(x => x.Table2) 
    .ToFuture(); 

// will load the Entities with Table3 fetched 
session.Query<Table1P>() 
    .FetchMany(x => x.Table3) 
    .ToFuture(); 

// will load the Entities with Table4 fetched 
session.Query<Table1P>() 
    .FetchMany(x => x.Table4) 
    .ToFuture(); 

// will load the Entities with Table6 fetched 
session.Query<Table1P>() 
    .FetchMany(x => x.Table6) 
    .ToFuture(); 

// will trigger all queries at once and the session cache will make sure, 
// that the results of all queries fill the same Entities 
allRecords.ToList(); 

변화

 .ToFuture() 
     .Take(3000); 

 .Take(3000); 
     .ToFuture() 

으로 업데이트 :이 가입에게 큰보다 느린 것을

// Hql 
var allRecords = session.CreateQuery("from Table1 left join fetch tbl1.Table2") 
    .ToFuture<Table1>(); 

... 

이상한. 나는 지금 여기서 시험 할 수 없다. 어쩌면 db의 행 수가 많아서 여러 결과 집합에 대한 오버 헤드가 extensiv 조인의 오버 헤드보다 클 수 있습니다. DB에서 더 많은 데이터를 사용해 볼 수 있습니까?

+0

제 생각에 저는 비슷한 것을 시도했습니다 (다시 시도 할 것입니다). 내가 알아 차 렸던 것은 그것이 실제로 한 번에 모든 것을 가지고있는 것은 실제로 더 천천히 그랬다라는 것이 었습니다. 나는 또한 더 많은 행을 따로 따로 따로 따로 따로 따로 따로 반환했음을 발견했다. (느린 이유 중 한 가지 이유). 예상 되나요? – chobo2

+0

아마도 느린 것은 아닙니다.비교하기 위해이 미래를 생각해 봐야 할 것입니다. (만약 모든 것을 하나의 시도로 해보려한다면, 메모리 부족이 발생합니다.) 이걸 가지고 내가 뭘 할 수 있을까? 모든 쿼리? 첫번째? Table1P에서 3000 행을 되찾기를 원한다고 가정 해 봅시다. 나머지는 테이블 1의 것들만받습니다. 또한 hql에서이 쿼리를 어떻게 수행합니까? – chobo2

+0

결과 수정을 참조하십시오. – chobo2

관련 문제