为什么我的查询这么慢?

时间:2013-10-23 13:28:16

标签: asp.net linq sql-server-2008

我尝试调整查询,但我不知道我可以改变什么:

  • 两个表格的屏幕截图:http://abload.de/image.php?img=1plkyg.jpg
  • 关系是:1 UserPM(私人消息)有1个发件人(User,SenderID - > User.SenderID)和1个收件人(User,RecipientID - > User.UserID)和1个用户有X个UserPM作为收件人和X UserPMs作为发件人。
  • 初始加载大约需要200毫秒,它只占用前20行并显示它们。显示此信息后,JavaScript PageMethod将获取GetAllPMsAsReciepient方法并加载其余数据
  • GetAllPMsAsReciepient方法每次大约需要花费4.5到5.0秒才能运行大约250行

我的代码:

    public static List<UserPM> GetAllPMsAsReciepient(Guid userID)
    {
        using (RPGDataContext dc = new RPGDataContext())
        {
            DateTime dt = DateTime.Now;

            DataLoadOptions options = new DataLoadOptions();
            //options.LoadWith<UserPM>(a => a.User);
            options.LoadWith<UserPM>(a => a.User1);
            dc.LoadOptions = options;

            List<UserPM> pm = (
                      from a in dc.UserPMs 
                      where a.RecieverID == userID 
                      && !a.IsDeletedRec 
                      orderby a.Timestamp descending select a
            ).ToList();

            TimeSpan ts = DateTime.Now - dt;
            System.Diagnostics.Debug.WriteLine(ts.Seconds + "." + ts.Milliseconds);

            return pm;
        }
    }

我不知道如何调整此查询,我的意思是250 PM什么都没有,在其他网站上的其他收件箱我得到5000左右或者它不需要一秒钟加载...

我尝试在时间戳上设置索引以减少Orderby时间,但到目前为止没有任何事情发生。

这里有什么想法吗?

修改

我尝试在LinqPad上重现它: 如果没有DataLoadOptions,在LinqPad中查询需要300毫秒,DataLoadOptions大约需要1秒。

所以,这意味着:

  • 我可以节省大约60%的时间,如果我可以避免在此查询中加载用户表,但是如何?
  • 为什么Linqpad在相同的连接上只需要1秒,来自同一台计算机,我的代码需要4.5-5.0秒?
  • 以下是执行计划:http://abload.de/image.php?img=54rjwq.jpg
  • 这是SQL Linqpad给我的:

SELECT [t0]。[PMID],[t0]。[Text],[t0]。[RecieverID],[t0]。[SenderID],[t0]。[Title],[t0]。[Timestamp ],[t0]。[IsDeletedRec],[t0]。[IsRead],[t0]。[IsDeletedSender],[t0]。[IsAnswered],[t1]。[UserID],[t1]。[用户名], [t1]。[密码],[t1]。[电子邮件],[t1]。[注册日期],[t1]。[LastLogin],[t1]。[RegisterIP],[t1]。[RefreshPing],[t1 ]。[Admin],[t1]。[IsDeleted],[t1]。[DeletedFrom],[t1]。[IsBanned],[t1]。[BannedReason],[t1]。[BannedFrom],[t1]。 [BannedAt],[t1]。[NowPlay],[t1]。[AcceptAGB],[t1]。[AcceptRules],[t1]。[MainProfile],[t1]。[SetShowHTMLEditorInRPGPosts],[t1]。[Age ],[t1]。[SetIsAgePublic],[t1]。[City],[t1]。[SetIsCityShown],[t1]。[Verified],[t1]。[Design],[t1]。[SetRPGCountPublic], [t1]。[SetLastLoginPublic],[t1]。[SetRegisterDatePublic],[t1]。[SetGBActive],[t1]。[Gender],[t1]。[IsGenderVisible],[t1]。[OnlinelistHidden],[t1 ]。[生日],[t1]。[SetIsMenuHideable],[t1]。[SetColorButtons],[t1]。[SetIsAboutMePublic],[t1]。[Name],[t1]。[SetIsNamePublic],[t1]。 [ContactAnimexx],[t1]。[ContactRPG Land],[t1]。[ContactSkype],[t1]。[ContactICQ],[t1]。[ContactDeviantArt],[t1]。[ContactFacebook],[t1]。[ContactTwitter],[t1]。[ContactTumblr] ,[t1]。[IsContactAnimexxPublic],[t1]。[IsContactRPGLandPublic],[t1]。[IsContactSkypePublic],[t1]。[IsContactICQPublic],[t1]。[IsContactDeviantArtPublic],[t1]。[IsContactFacebookPublic],[ t1]。[IsContactTwitterPublic],[t1]。[IsContactTumblrPublic],[t1]。[IsAdult],[t1]。[IsShoutboxVisible],[t1]。[Notification],[t1]。[ShowTutorial],[t1] 。[MainProfilePreview],[t1]。[SetSound],[t1]。[EmailNotification],[t1]。[UsernameOld],[t1]。[UsernameChangeDate] 来自[UserPM] AS [t0] INNER JOIN [用户] AS [t1] ON [t1]。[UserID] = [t0]。[RecieverID] WHERE([t0]。[RecieverID] = @ p0)AND(NOT([t0]。[IsDeletedRec] = 1)) ORDER BY [t0]。[时间戳] DESC

2 个答案:

答案 0 :(得分:0)

如果你想摆脱LoadWith,你可以明确地选择你的字段:

public static List<Tuple<UserPM, User> > GetAllPMsAsReciepient(Guid userID)
{
    using (var dataContext = new RPGDataContext())
    {
        return (
            from a in dataContext.UserPMs 
            where a.RecieverID == userID 
            && !a.IsDeletedRec 
            orderby a.Timestamp descending 
            select Tuple.Create(a, a.User1)
        ).ToList();
    }
}

答案 1 :(得分:0)

我找到了解决方案:

起初,看起来DataLoadOptions是不合适的,第二,当你只需要1时,加载一个包含30个Coloumns的表并不聪明。

为了解决这个问题,我制作了一个涵盖所有nececeery字段的视图,当然还有连接。

它将时间从5.0秒减少到230毫秒!