2016-07-25 113 views
0

我有一個cron-job方法,它根據用戶的精選故事,後續類別和關注用戶構建用戶的故事饋送。提高代碼性能

最終進料在以下數據庫表中加入正確的順序:
UserFeed表:

的Uid         StoryListIds
              3,23, 45,3,6,234,.....
              3,23,45,6,87,44,...
              3,23,45,32,如圖4所示,62,... ..

該方法如下,幷包含註釋。
的代碼:

public void ConstructUserFeed() 
     { 
      try 
      { 
       //get all user ids 
       var userIds = userBL.GetIds(); 
       //get all featured stories 
       var featStories = storyBL.GetFeaturedStories(); 

       if (userIds != null && userIds.Count > 0) 
       { 
        foreach (var userId in userIds) 
        { 
         //integer List to store the stories ids in correct order 
         List<int> storyIdsLst = new List<int>(); 
         //integer List for excluding duplicates 
         List<int> exceptStoryIds = new List<int>(); 
         //user feed List to store the stories 
         var userFeed = new List<UserFeedDTO>(); 
         //string to store the id list so we can add it later in db 
         string storyIds = ""; 

         if (featStories != null && featStories.Count > 0) 
         { 
          foreach (var featStory in featStories) 
          { 
           //first add all the ids of featured stories except own user stories, ordered by date 
           if (featStory.authorId != userId) 
           { 
            storyIdsLst.Add(featStory.id); 
            exceptStoryIds.Add(featStory.id); 
           } 
          } 
         } 

         //get user's followed categories ids 
         var followedCategoryIds = userCategoriesBL.GetFollowedCategoryIds(userId); 

         if (followedCategoryIds != null && followedCategoryIds.Count > 0) 
         { 
          foreach (var categoryId in followedCategoryIds) 
          { 
           //get the user's 5 latest stories for every followed category 
           //except own stories and previous stories 
           var storiesByCateg = storyBL.GetByCategory(5, categoryId, userId, exceptStoryIds); 

           if (storiesByCateg != null && storiesByCateg.Count > 0) 
           { 
            foreach (var storyByCateg in storiesByCateg) 
            { 
             userFeed.Add(storyByCateg); 
             exceptStoryIds.Add(storyByCateg.id); 
            } 
           } 
          } 
         } 

         //get user's followed users ids 
         var followedUserIds = userFollowersBL.GetFollowedUserIds(userId); 

         if (followedUserIds != null && followedUserIds.Count > 0) 
         { 
          foreach (var followedId in followedUserIds) 
          { 
           //get the user's 5 latest stories for every followed user 
           //except own stories and previous stories 
           var storiesByFollowedUsers = storyBL.GetByFollowedUser(5, followedId, userId, exceptStoryIds); 

           if (storiesByFollowedUsers != null && storiesByFollowedUsers.Count > 0) 
           { 
            foreach (var storyByFollowedUsers in storiesByFollowedUsers) 
            { 
             userFeed.Add(storyByFollowedUsers); 
            } 
           } 
          } 
         } 

         // order the stories by date 
         userFeed = userFeed.OrderByDescending(story => story.dateAdded).ToList(); 

         if (userFeed != null && userFeed.Count > 0) 
         { 
          foreach (var story in userFeed) 
          { 
           //add the story ids after the featured story ids 
           storyIdsLst.Add(story.id); 
          } 
         } 

         //comma separated list of story ids as string so we can store it in db 
         storyIds = string.Join(",", storyIdsLst.Select(n => n.ToString()).ToArray()); 

         //create the UserFeed model 
         UserFeed userFeedModel = new UserFeed(); 
         userFeedModel.userId = userId; 
         userFeedModel.storyListId = storyIds; 
         userFeedModel.lastUpdateTime = DateTime.Now; 

         userFeedBL.AddOrUpdateUserFeed(userFeedModel); 
        } 
        uof.Save(); 
       } 
      } 

      catch (Exception ex) 
      { 
       Console.WriteLine("Error occurred in processing job. Error : {0}", ex.Message); 
      } 
     } 

,上述方法需要〜35秒來完成30個用戶。
問:我該如何改進我的代碼和性能?

+1

你可以考慮在存儲過程中使用它嗎? –

回答

1

很難說究竟是什麼原因導致它執行得太慢,因爲我建議用SQL Server Profiler來分析你的問題。檢查您的查詢是否被正確詢問,並且沒有做任何不必要的事情。

之後,我會考慮詢問更少的問題。既然你在做循環,你可能會受益於更少,但更重的問題。例如(假設userFollowersBL *被查詢DB):

var followedCategoryIds = userCategoriesBL.GetFollowedCategoryIds(userId); 

我認爲簽名是這樣的:

IEnumerable<int> GetFollowedCategoryIds(userId); 

考慮將其更改爲:

IDictionary<int, IEnumerable<int>> GetFollowedCategoryIds(IEnumerable<int> userIds); 

然後你在開始你的foreach之前,會有一個字典,其中包含userids和他們的每個followCategoryId。通過這種方式,您可以在一個查詢中發送來自userBL.GetIds()的所有結果。它可能加速性能做一次,而不是30次。 userFollowersBL.GetFollowedUserIds(userId)也是一樣。

現在您已減少查詢數量到您的DB與約58倍

public void ConstructUserFeed() 
     { 
      try 
      { 
       //get all user ids 
       var userIds = userBL.GetIds(); 
       //get all featured stories 
       var featStories = storyBL.GetFeaturedStories(); 

// Fetch all in one query. 
IDictionary<int,IEnumerable<int>> allFollowedCategoryIds= userCategoriesBL.GetFollowedCategoryIds(userIds); 
// Fetch all in one query 
IDictionary<int,IEnumerable<int>> allUserFollowers = userFollowersBL.GetFollowedUserIds(userIds); 

       if (userIds != null && userIds.Count > 0) 
       { 
        foreach (var userId in userIds) 
        { 
         //integer List to store the stories ids in correct order 
         List<int> storyIdsLst = new List<int>(); 
         //integer List for excluding duplicates 
         List<int> exceptStoryIds = new List<int>(); 
         //user feed List to store the stories 
         var userFeed = new List<UserFeedDTO>(); 
         //string to store the id list so we can add it later in db 
         string storyIds = ""; 

         if (featStories != null && featStories.Count > 0) 
         { 
          foreach (var featStory in featStories) 
          { 
           //first add all the ids of featured stories except own user stories, ordered by date 
           if (featStory.authorId != userId) 
           { 
            storyIdsLst.Add(featStory.id); 
            exceptStoryIds.Add(featStory.id); 
           } 
          } 
         } 

         //get user's followed categories ids 
         var followedCategoryIds = allFollowedCategoryIds[userId] 

         if (followedCategoryIds != null && followedCategoryIds.Count > 0) 
         { 
          foreach (var categoryId in followedCategoryIds) 
          { 
           //get the user's 5 latest stories for every followed category 
           //except own stories and previous stories 
           var storiesByCateg = storyBL.GetByCategory(5, categoryId, userId, exceptStoryIds); 

           if (storiesByCateg != null && storiesByCateg.Count > 0) 
           { 
            foreach (var storyByCateg in storiesByCateg) 
            { 
             userFeed.Add(storyByCateg); 
             exceptStoryIds.Add(storyByCateg.id); 
            } 
           } 
          } 
         } 

         //get user's followed users ids 
         var followedUserIds = allUserFollowers[userId]; 

         if (followedUserIds != null && followedUserIds.Count > 0) 
         { 
          foreach (var followedId in followedUserIds) 
          { 
           //get the user's 5 latest stories for every followed user 
           //except own stories and previous stories 
           var storiesByFollowedUsers = storyBL.GetByFollowedUser(5, followedId, userId, exceptStoryIds); 

           if (storiesByFollowedUsers != null && storiesByFollowedUsers.Count > 0) 
           { 
            foreach (var storyByFollowedUsers in storiesByFollowedUsers) 
            { 
             userFeed.Add(storyByFollowedUsers); 
            } 
           } 
          } 
         } 

         // order the stories by date 
         userFeed = userFeed.OrderByDescending(story => story.dateAdded).ToList(); 

         if (userFeed != null && userFeed.Count > 0) 
         { 
          foreach (var story in userFeed) 
          { 
           //add the story ids after the featured story ids 
           storyIdsLst.Add(story.id); 
          } 
         } 

         //comma separated list of story ids as string so we can store it in db 
         storyIds = string.Join(",", storyIdsLst.Select(n => n.ToString()).ToArray()); 

         //create the UserFeed model 
         UserFeed userFeedModel = new UserFeed(); 
         userFeedModel.userId = userId; 
         userFeedModel.storyListId = storyIds; 
         userFeedModel.lastUpdateTime = DateTime.Now; 

         userFeedBL.AddOrUpdateUserFeed(userFeedModel); 
        } 
        uof.Save(); 
       } 
      } 

      catch (Exception ex) 
      { 
       Console.WriteLine("Error occurred in processing job. Error : {0}", ex.Message); 
      } 
     } 

但說實話,這主要是猜測,可能會不時地有所不同。根據我的經驗,您傾向於從詢問更多數據中獲益一次,而不是相同的數據多次。

+0

你的意思是創建一個IDictionary 列表爲跟隨的類別和用戶? – alex

+1

是的,但我寫錯了。我想它需要'IDictionary >' – smoksnes

+0

,減少運行時間到一半,thx – alex