通过ID列表搜索数据库中记录

问题描述 投票:1回答:3

我有ID(ITEMID的),我传递给像下面查询的列表:

 using (var ctx = new MyEntities())
            {
                ctx.Configuration.LazyLoadingEnabled = false;
                ctx.Configuration.AutoDetectChangesEnabled = false;
                ctx.Configuration.ValidateOnSaveEnabled = false;
                ctx.Configuration.ProxyCreationEnabled = false;
                var storeItems = ctx.Items.AsNoTracking().Where(y => y.StoreID == 223250).ToList();
                var idList = storeItems.Select(y => y.Id).ToList();
                var storeTransactions = ctx.ItemTransactions.AsNoTracking().Where(r => idList.Contains(r.Id.Value)).ToList();
                return Json("Ok");
            }

为了快速概括起来......例如1001项StoreItems名单在这种情况下...

并通过将1001项ID来获取项目交易我回来的结果

265000个记录...

这两个表都没有任何关系连接,但ID列索引,以提高结果...

然而,最后的查询性能绝对是可怕的,时间超过一分钟更全面完成选择所有记录,即使所有我已经加入到它加速它的调整,但它仍然没有帮助....

有谁知道,如果仍然有我失踪的项目获取交易时加快速度在这最后询问些什么呢?

有人可以帮我吗?

c# asp.net asp.net-mvc performance linq
3个回答
1
投票

你写了:

两个表不被任何关系连接

那么显然有一定的关系。您预计ItemTranaction.Id.Value具有Item.Id有时值

你得到的所有项目与STOREID等于223250.从这些项目的项目获取的ID。给我说,有一个Id.Value,这也是在所获取的ID的所有ItemTransactions。

换一种说法:

要求:给我你所有项目的交易,这对项目Transaction.Id.Value等于一个值,所有物品的ID之一,STOREID等于223250

您的查询会快很多,如果你在一个查询做到这一点:

int storeId = 223250;

var result = dbContext.ItemTransactions
  .Join(dbContext.Items.Where(item => item.StoreId == storeId),
  itemTransaction => itemTransaction.Id.Value,
  item => item.Id,
  (itemtransaction, item) => itemTransaction)

在的话:

  • 加入与具有等于storId一个STOREID项目的itemtransaction。
  • 从每itemTransaction采取itemTransaction.Id.Value,
  • 从每个项目采取的Id
  • 当这些值相等,以itemTransaction和项目来创建一个结果
  • 这个结果是itemTransaction

你没有这么说,但我认为item.Id是主键。这可确保没有两个项目使用相同的ID,因此,所有剩余itemTransactions是唯一的。不同的是没有必要的。


2
投票

问题是你得到可操作的ID来存储的列表,然后用它来再次查询。这意味着所有的ID硬编码EF将它翻译为一个简单的IN查询。其实我甚至怀疑,因为265000个记录数过高,它实际上将首先获得所有从DB的ItemTransactions然后做查询在内存中。这会导致糟糕的表现。但是一个简单的变化将使得业绩显著更好:

using (var ctx = new MyEntities())
{
    ctx.Configuration.LazyLoadingEnabled = false;
    ctx.Configuration.AutoDetectChangesEnabled = false;
    ctx.Configuration.ValidateOnSaveEnabled = false;
    ctx.Configuration.ProxyCreationEnabled = false;
    var storeItems = ctx.Items.AsNoTracking().Where(y => y.StoreID == 223250);
    var idList = storeItems.Select(y => y.Id); //removed ToList on this and previous line
    var storeTransactions = ctx.ItemTransactions.AsNoTracking()
                               .Where(r => idList.Contains(r.Id.Value)).ToList();
    return Json("Ok");
}

我所做的唯一的变化是在你的代码中删除ToList()电话。这将意味着idListIQueryable<int>其中EF能理解并代替第一执行它,它就会用它作为最后一条语句子查询或JOIN - 这将有显著更好的性能。

也可以考虑,如果你确实需要的ItemTransactions情况下,作为一个整体,也可以使用投影与Select查询只有你实际需要的性能。这将减少必须您的应用程序和数据库之间传输的数据量。


1
投票

无需数据库禁用LazyLoadingEnabled选项,并利用AsQueryable,使ids不会是在内存中。我会建议在这种情况下使用join

尝试这个:

using ( var ctx = new MyEntities() )
{
    ctx.Configuration.LazyLoadingEnabled = true;
    ctx.Configuration.AutoDetectChangesEnabled = false;
    ctx.Configuration.ValidateOnSaveEnabled = false;
    ctx.Configuration.ProxyCreationEnabled = false;

    var idList = ctx.Items.AsNoTracking().Where( y => y.StoreID == 223250 ).Select( y => y.Id ).AsQueryable();

    var storeTransactions = ctx.ItemTransactions.AsNoTracking().Where( r => idList.Contains( r.Id.Value ) ).ToList();

    return Json( "Ok" );
}
© www.soinside.com 2019 - 2024. All rights reserved.