LINQ 데이터 추출 최적화에 필요한 도움
-
22-07-2019 - |
문제
네트워크 대기 시간을 피하기 위해 3 개의 테이블 모두에서 한 번에 데이터를 가져오고 있습니다. 데이터를 가져 오는 것은 매우 빠르지 만 결과를 살펴보면 많은 시간이 사용됩니다.
Int32[] arr = { 1 };
var query = from a in arr
select new
{
Basket = from b in ent.Basket
where b.SUPERBASKETID == parentId
select new
{
Basket = b,
ObjectTypeId = 0,
firstObjectId = "-1",
},
BasketImage = from b in ent.Image
where b.BASKETID == parentId
select new
{
Image = b,
ObjectTypeId = 1,
CheckedOutBy = b.CHECKEDOUTBY,
firstObjectId = b.FIRSTOBJECTID,
ParentBasket = (from parentBasket in ent.Basket
where parentBasket.ID == b.BASKETID
select parentBasket).ToList()[0],
},
BasketFile = from b in ent.BasketFile
where b.BASKETID == parentId
select new
{
BasketFile = b,
ObjectTypeId = 2,
CheckedOutBy = b.CHECKEDOUTBY,
firstObjectId = b.FIRSTOBJECTID,
ParentBasket = (from parentBasket in ent.Basket
where parentBasket.ID == b.BASKETID
select parentBasket),
}
};
//Exception handling
var mixedElements = query.First();
ICollection<BasketItem> basketItems = new Collection<BasketItem>();
//Here 15 millis has been used
//only 6 elements were found
if (mixedElements.Basket.Count() > 0)
{
foreach (var mixedBasket in mixedElements.Basket){}
}
if (mixedElements.BasketFile.Count() > 0)
{
foreach (var mixedBasketFile in mixedElements.BasketFile){}
}
if (mixedElements.BasketImage.Count() > 0)
{
foreach (var mixedBasketImage in mixedElements.BasketImage){}
}
//the empty loops takes 811 millis!!
해결책
Foreach 진술 전에 수를 확인하려는 이유는 무엇입니까? 결과가 없으면 Foreach가 즉시 완료됩니다.
귀하의 쿼리는 실제로 모두 연기됩니다. 데이터를 요청할 때와 같이 실행됩니다. 가장 바깥 쪽 쿼리가 LINQ To Objects Query라는 것을 잊지 마십시오. ent.Basket.Where(...).Select(...)
등 ... 실제로 쿼리를 실행하지 않습니다.
한 번에 세 가지 쿼리를 모두 수행하려는 계획은 실제로 작동하지 않습니다. 그러나 카운트를 별도로 요청하면 실제로 각 데이터베이스 쿼리를 두 번 실행할 수 있습니다.
이 코드에서 "최적화"를 제거하여 훨씬 더 복잡하고 느리게 가장 간단한 코드를 작성하는 것보다.
LINQ에서 SQL (또는 LINQ에서 EF)을 한 번의 호출에서 여러 쿼리를 실행하는 방법은 모르겠지만이 접근법은 확실히 그렇게하지 않을 것입니다.
이 경우 관련이 있지만 LINQ에서 객체에 유용 할 수있는 다른 사소한 힌트 중 하나입니다. 컬렉션에 데이터가 있는지 여부를 알아 보려면 사용하십시오. Any()
대신에 Count() > 0
- 그런 식으로 발견 되 자마자 멈출 수 있습니다.
다른 팁
당신은 사용하고 있습니다 IEnumerable
Foreach 루프에서. 구현은 요청할 때만 데이터를 준비하면됩니다. 이런 식으로 위의 코드가 데이터에 게으르게 액세스 할 것을 제안합니다. 즉, 항목을 열거 할 때만 (실제로 전화 할 때 발생하는 경우에만 가능합니다. Count()
.)
a System.Diagnostics.Stopwatch
전화 주위 Count()
그리고 그것이 당신이보고있는 시간의 대부분을 취하고 있는지 확인하십시오.
나는 당신이 ent
코드 샘플에서.