2016-07-25 12 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); 
      } 
     } 

は、上記の方法は、30人のユーザーのために完了するために、〜35秒かかります。
Q:コードとパフォーマンスを改善するにはどうすればよいですか?

+1

ストアドプロシージャで実行することはできますか? –

答えて

1

これはゆっくりと実行される原因を正確に言うのは難しいです。そのために質問をSQL Server Profilerでプロファイリングすることをお勧めします。あなたの質問が正しく尋ねられ、何も不要でないことを確認してください。

その後、私はより少ない質問を尋ねると考えます。あなたはループでそれをやっているので、の数が少なくてもであることが恩恵を受けるかもしれませんが、より重い質問です。例えば、(userFollowersBLを仮定* DBを照会している。):

var followedCategoryIds = userCategoriesBL.GetFollowedCategoryIds(userId); 

私は署名のようなものであることを前提としています。あなたが次に

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

IEnumerable<int> GetFollowedCategoryIds(userId); 

はそれを変更することを検討してくださいあなたのforeachを始める前に、useridsとそれぞれの後続のCategIdsを持つ辞書をメモリに入れておきます。このようにして、すべての結果をuserBL.GetIds()から1つのクエリで送信できます。それはかもしれない 30倍の代わりに1回、それを行うパフォーマンスを向上させます。同じことがuserFollowersBL.GetFollowedUserIds(userId)になります。

約58時間でDBのクエリ数を減らしました。

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

でなければならないと思います。 – alex

関連する問題