为什么这个linq查询的匿名类型比我尝试的任何其他类型更快?

时间:2013-11-21 14:45:31

标签: c# sql performance linq

我有这个查询,它从表中选择了很多用户记录。这个代码块从我的本地/调试机器需要16秒(在生产中更像是5)。为了提高效率,我所做的任何事情都会使方法返回结果所花费的时间增加一倍。我尝试过的其他事情的例子如下。我不明白如何选择一个匿名类型并让额外的中间部分迭代通过匿名类型可能比没有它更快。

此块需要16秒:

List<BoAssetSecurityUser> userList = new List<BoAssetSecurityUser>();
using (var context = DataObjectFactory.CreateContext())
{

    var query = from ui in context.User_Information
                where (ui.AssetCustomerID == 1 && 
                          (ui.GlobalID != "1TPTEMPUSER" || 
                           ui.GlobalID == null))
                select new { ui };
    var result =
    from q in query
    select new
    {
        UserId = q.ui.UserID,
        FirstName = q.ui.FirstName,
        LastName = q.ui.LastName,
        UserName = q.ui.Username,
        Globalid = q.ui.GlobalID

    };
    foreach (var user in result)
    {
        BoAssetSecurityUser boAssetSecUser = new BoAssetSecurityUser();
        boAssetSecUser.UserId = user.UserId;
        boAssetSecUser.FirstName = user.FirstName;
        boAssetSecUser.LastName = user.LastName;
        boAssetSecUser.UserName = user.UserName;
        boAssetSecUser.GlobalId = user.Globalid;
        userList.Add(boAssetSecUser);
    }
}
return userList;

这需要45秒才能完成:

List<BoAssetSecurityUser> userList = new List<BoAssetSecurityUser>();
using (var context = DataObjectFactory.CreateContext())
{

    var query = (from ui in context.User_Information
                where (ui.AssetCustomerID == 1 && 
                          (ui.GlobalID != "1TPTEMPUSER" || 
                           ui.GlobalID == null))
                select ui).ToList();
    foreach (var user in query)
    {
        BoAssetSecurityUser boAssetSecUser = new BoAssetSecurityUser();
        boAssetSecUser.UserId = user.UserID;
        boAssetSecUser.FirstName = user.FirstName;
        boAssetSecUser.LastName = user.LastName;
        boAssetSecUser.UserName = user.Username;
        boAssetSecUser.GlobalId = user.GlobalID;
        userList.Add(boAssetSecUser);
    }
}
return userList;

此示例还需要45秒才能完成:

List<BoAssetSecurityUser> userList = new List<BoAssetSecurityUser>();
using (var context = DataObjectFactory.CreateContext())
{

    var query = from ui in context.User_Information
        where (ui.AssetCustomerID == 1 && 
                  (ui.GlobalID != "1TPTEMPUSER" || 
                   ui.GlobalID == null))
                select new { ui };

    foreach (var user in query)
    {
        BoAssetSecurityUser boAssetSecUser = new BoAssetSecurityUser();
        boAssetSecUser.UserId = user.ui.UserID;
        boAssetSecUser.FirstName = user.ui.FirstName;
        boAssetSecUser.LastName = user.ui.LastName;
        boAssetSecUser.UserName = user.ui.Username;
        boAssetSecUser.GlobalId = user.ui.GlobalID;

        userList.Add(boAssetSecUser);
    }
}
return userList;

3 个答案:

答案 0 :(得分:5)

这很可能是因为ui的类型具有比您感兴趣的5更多的属性。new { ui }匿名类型是不必要的;您的第一个示例更快,因为您在迭代列表(因此转到数据库)之前告诉它您只对这5个字段感兴趣。在其他示例中,您迭代列表,从而拉动整个ui对象,即使您只使用其5个属性。

此代码应仅提取5个属性,因此与第一个示例一样快,同时更简洁:

List<BoAssetSecurityUser> userList = new List<BoAssetSecurityUser>();
using (var context = DataObjectFactory.CreateContext())
{
    var query = from ui in context.User_Information
                where (ui.AssetCustomerID == 1 && (ui.GlobalID != "1TPTEMPUSER" || ui.GlobalID == null))
                select new
                {
                    ui.UserID,
                    ui.FirstName,
                    ui.LastName,
                    ui.Username,
                    ui.GlobalID
                };

    foreach (var user in query)
    {
        BoAssetSecurityUser boAssetSecUser = new BoAssetSecurityUser();
        boAssetSecUser.UserId = user.UserID;
        boAssetSecUser.FirstName = user.FirstName;
        boAssetSecUser.LastName = user.LastName;
        boAssetSecUser.UserName = user.Username;
        boAssetSecUser.GlobalId = user.GlobalID;
        userList.Add(boAssetSecUser);
    }
}
return userList;

答案 1 :(得分:1)

它更多地是关于您从数据库中提取的数据量。第一个查询只选择几列,而其他列则选择所有列。

这张桌子上有大栏吗?

答案 2 :(得分:1)

它更快,因为您只使用匿名类型每行获取5个属性。我现在没有User_Information中有多少个字段,但是当您在查询中使用.ToList()时,它们都会被提取,您可能获得的数据远远超过所需数据。