Linq-версия SQL-запроса с несколькими объединениями и групповыми байтами - PullRequest
0 голосов
/ 07 марта 2012

При попытке написать этот запрос из устаревшей базы данных в linq я столкнулся с проблемами производительности.Есть ли лучший способ написать приведенный ниже запрос sql в linq.

Выполнение запроса sql занимает менее 2 секунд, тогда как текущее выражение linq занимает более 6 секунд.

Это изБД SQL 2008R2.

Вот запрос sql

SELECT  People.ID,
        A.GameKey, 
        ClubCode, 
        case
            WHEN ClubCode = Home_TM_CD then Visit_TM_CD
            WHEN ClubCode = Visit_TM_CD then Home_TM_CD
        end as Opponent,            
        count(case when (ClubCode <> PossessionTeam and STPlayType = 0)  then 'super' end) as super_plays,
        (SELECT count(PlayID) 
         FROM   PLAY_LIST B 
         WHERE  A.GameKey = B.GameKey
         AND    ClubCode <> PossessionTeam 
         AND    PossessionTeam <> ''
         AND    STPlayType = 0 
         GROUP BY A.GameKey, A.ClubCode) as Total_Super_Play,
        count(case when (ClubCode = PossessionTeam and STPlayType = 0) then 'plays' end) as plays,
        (SELECT count(PlayID) 
         FROM   PLAY_LIST B 
         WHERE  A.GameKey = B.GameKey
         AND    ClubCode = PossessionTeam 
         AND    STPlayType = 0 
         GROUP BY A.GameKey, A.ClubCode) as Total_Play,         
        Season,
        Season_Type,
        Week,
        Game_DT
    FROM    PEOPLE
    INNER JOIN PEOPLE_PARTICIPATION A ON People.ID = A.ID
    inner join GAME on GameKey  = gamekey
    inner join PLAY_LIST on PLAY_LIST.GameKey = A.GameKey AND PLAY_LIST.PlayID = A.PlayID
    WHERE   Season = 2011       
    and     People.ID = 1
    group by    People.ID,
                Season,
                Season_Type,
                Week,
                Game_DT,
                A.GameKey,
                ClubCode,
                Home_TM_CD, 
                Visit_TM_CD
    order by Season, 
             CASE WHEN Season_Type = 'Reg' THEN 1 ELSE 2 END, week, People.ID

Вот выражение linq, которое у меня есть

IQueryable<ProViewModel> playerList = (from people in db.PEOPLE
join participation in db.PARTICIPATION on people.ID equals participation.ID
join game in db.GAME on participation.GameKey equals game.Gamekey    
join playlist in db.PLAY_LIST on new { gamekey = participation.GameKey, playID = participation.PlayID } equals new { gamekey = playlist.GameKey, playID = playlist.PlayID }                                                                                    
where people.ID == 1 &&
game.Season == 2011
group playlist by new PeopleParticipationGroup{
   ID = people.ID,
   SEASON = game.Season,
   SEASON_TYPE = game.Season_Type,
   WEEK = game.Week,
   GAME_DT = game.Game_DT,
   GameKey = participation.GameKey,
   ClubCode = participation.ClubCode,
   HOME_TM_CD = game.Home_TM_CD,
   VISIT_TM_CD = game.Visit_TM_CD
} into groupedPeople
orderby groupedPeople.Key.SEASON                                                  
select new PeopleViewModel 
{   
   ID = groupedPeople.Key.ID,
   SEASON_TYPE = groupedPeople.Key.SEASON_TYPE,
   WEEK = groupedPeople.Key.WEEK,
   SEASON_TYPE_SORT = 
   (
    groupedPeople.Key.SEASON_TYPE == "REG" ? 1 :
    groupedPeople.Key.SEASON_TYPE == "POST" ? 2 : 3
   ),
   GAME_DT = groupedPeople.Key.GAME_DT,
   SEASON = groupedPeople.Key.SEASON,
   GameKey = groupedPeople.Key.GameKey,
   ClubCode = groupedPeople.Key.ClubCode,
   Opponent = 
   (
    groupedPeople.Key.ClubCode == groupedPeople.Key.HOME_TM_CD ? groupedPeople.Key.VISIT_TM_CD : groupedPeople.Key.HOME_TM_CD
   ),
   HOME_TM_CD = groupedPeople.Key.HOME_TM_CD,
   VISIT_TM_CD = groupedPeople.Key.VISIT_TM_CD,                                                       
   PLAYS = (from t in groupedPeople
                      where t.PossessionTeam == groupedPeople.Key.ClubCode && 
                      t.STPlayType == 0
                      select t).Count(),                                                       
   TOTAL_PLAYS = (from p in db.PLAY_LIST
                            where p.GameKey == groupedPeople.Key.GameKey && 
                            p.PossessionTeam == groupedPeople.Key.ClubCode && 
                            p.PossessionTeam != "" &&                                                                                 
                            p.STPlayType == 0
                            select p).Count(),
   SUPER_PLAYS = (from t in groupedPeople
                      where t.PossessionTeam != groupedPeople.Key.ClubCode && 
                      t.STPlayType == 0
                      select t).Count(),
   TOTAL_SUPER_PLAYS = (from p in db.PLAY_LIST
                            where p.GameKey == groupedPeople.Key.GameKey &&
                            p.PossessionTeam == groupedPeople.Key.ClubCode &&
                            p.PossessionTeam == "" &&
                            p.STPlayType == 0
                            select p).Count(),                                                       
}); ;

1 Ответ

0 голосов
/ 07 марта 2012

Я не совсем уверен, как скомпилированы запросы и сколько сделано оптимизации. Если он работает так, как я ожидаю, и преобразует запрос в порядке его определения в вызовы функций linq, то изменение порядка может помочь.

Например, вы можете удалить

where people.ID == 1 &&
game.Season == 2011

и замену db.PEOPLE на db.PEOPLE.where(p => p.id == 1) и аналогичную замену db.GAME.

Это позволило бы избежать работы по объединению результатов, которые впоследствии будут отброшены. Поскольку у вас есть эти константы, возможно, стоит вывести их из группировки и сразу в выборку.

С другой стороны, если предположить, что это LINQ to SQL, то приведенное выше, вероятно, не поможет, и вы можете использовать db.Log , чтобы увидеть, на что запрос транслируется в SQL. Затем вы можете изменить порядок, пока ваш LINQ не совпадет или не улучшит исходный SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...