Въпрос за производителност между две Linq заявки в LinqPad и на практика

Имам запитване:

(from sr in ctx.STARS_Route
                            where sr.STARS_RouteStopDestination.Any(i => i.IsWorkingSet == true && i.STARS_DistrictRoute.DistrictId == districtId) == true
                            select sr.DistrictRouteNumber).Distinct();

В LinqPad заявката се изпълняваше за приблизително 0,3 секунди. Има приблизително 800K записа в таблицата STARS_RouteStopDestination, но средната възвръщаемост е около 30-90 записа.

На практика методът, връщащ резултатите от тази заявка, отнемаше 4+ секунди! Нямаше никакъв смисъл.

Единственото нещо, за което се сетих е, че клаузата .Any отнема много време, но LinqPad каза, че заявката е бърза. Настроих тест (моля за извинение за имената):

using (STARSEntities ctx = new STARSEntities())
        {
            var Original = (from sr in ctx.STARS_Route
                            where sr.STARS_RouteStopDestination.Any(i => i.IsWorkingSet == true && i.STARS_DistrictRoute.DistrictId == districtId) == true
                            select sr.DistrictRouteNumber).Distinct();

            var Entity = (from rsd in ctx.STARS_RouteStopDestination
                          where rsd.STARS_DistrictRoute.DistrictId == districtId
                          && rsd.IsWorkingSet == true
                          select rsd.STARS_Route.DistrictRouteNumber).Distinct();

            DateTime startOriginal = DateTime.Now;
            routes = Original.ToList();
            Debug.WriteLine("Original took: " + (DateTime.Now - startOriginal).ToString());
            DateTime startEtity = DateTime.Now;
            routes = Entity.ToList();
            Debug.WriteLine("Entity took: " + (DateTime.Now - startEtity).ToString());
        }

Резултатът ми взриви ума:
Оригиналът взе: 00:00:04.0270000
Обектът взе: 00:00:00.0200000

Защо изпълнението на заявката с клаузата .Any отнема много повече време и защо LinqPad би казал, че оригиналната заявка се изпълнява малко по-бързо от заявката Entity срещу същия набор от данни?


person Noel    schedule 05.04.2011    source източник
comment
Какво се случва, ако изпълните заявки в обратен ред?   -  person Ladislav Mrnka    schedule 05.04.2011
comment
Предпочитам да използвам клас StopWatch в System.Diagnostics за измерване на времето за изпълнение вместо DateTime.   -  person Diego Torres    schedule 05.04.2011
comment
Обратна страна: Обектът е взет: 00:00:00.0170000 Оригиналът е взет: 00:00:04.0890000   -  person Noel    schedule 05.04.2011
comment
Бих изпълнил и двете заявки и бих активирал SQL Profiler и ще видя как изглеждат SQL заявките, които стигат до вашия SQL сървър. Това може да ви даде повече представа за разликата в производителността.   -  person Rus    schedule 05.04.2011
comment
Ако използвате LinqPad, трябва да можете да видите генерирания SQL. Може би това може да хвърли малко светлина. IIRC EF има по-добро генериране на SQL от L2S.   -  person DaveShaw    schedule 05.04.2011
comment
В LINQPad използвате ли автоматично генериран DataContext (т.е. LINQ към SQL) или се свързвате към вашия модел на Entity Framework?   -  person Joe Albahari    schedule 06.04.2011
comment
@Joe - Не се свързвам директно с моя EF модел, а само с генерирания. Схемата на db не се е променила от последното актуализиране на EF модела в моя проект.   -  person Noel    schedule 07.04.2011
comment
Ако използвате генерирания модел на LINQPad, вие използвате LINQ към SQL, който произвежда различен (и обикновено по-добър) SQL от Entity Framework. Във всеки случай разделът за SQL превод на LINQPad трябва да ви каже какъв SQL се генерира. Можете също така да се свържете с вашия EF модел в LINQPad и да сравните.   -  person Joe Albahari    schedule 08.04.2011


Отговори (1)


Вие просто действате върху два различни обекта, които имат две различни стратегии за получаване на резултата. LINQPad генерира LINQ към SQL модел и инжектира вашия код в метод с този модел в обхвата.

Вашият клас STARSEntities е от различен тип и вероятно има напълно различно взаимодействие с базата данни.

LINQPad има собствен изглед, който показва изпълнявания SQL. Трябва да го сравните с SQL, изпълняван от EF модела. Това се показва в SQL Server Profiler, когато изпълнявате.

person Tormod    schedule 31.07.2011