C# 通过ID列表搜索数据库中的记录
我有一个ID itemID的列表,我将其传递给查询,如下所示:C# 通过ID列表搜索数据库中的记录,c#,asp.net,asp.net-mvc,performance,linq,C#,Asp.net,Asp.net Mvc,Performance,Linq,我有一个ID itemID的列表,我将其传递给查询,如下所示: using (var ctx = new MyEntities()) { ctx.Configuration.LazyLoadingEnabled = false; ctx.Configuration.AutoDetectChangesEnabled = false; ctx.Configuration.Vali
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");
}
快速总结一下。。。StoreItems列表,例如本例中的1001项
通过传递1001 item id来获取item事务,我得到了返回的结果
265000张唱片
这两个表没有通过任何关系连接,但是Id列被索引以改进结果
然而,上一次查询的性能非常糟糕,需要一分钟以上的时间才能完全选择完所有记录,即使我对其进行了所有的调整以加快速度,但仍然没有任何帮助
有人知道在获取项目事务时,我是否还缺少一些东西来加快最后一个查询的速度吗
有人能帮我吗?问题是您将可操作ID列表存储到内存中,然后使用它再次查询。这意味着EF将把它转换为一个简单的IN查询,并对所有ID进行硬编码。实际上,我甚至怀疑,由于265000条记录的数量太多,它实际上会首先从数据库中获取所有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调用。这意味着idList是EF可以理解的IQueryable,它不会首先执行它,而是在最后一条语句中将它用作子查询或联接,这将具有更好的性能
还考虑如果您实际上需要ItMeExchange实例作为一个整体,或者您可以使用带有选择的投影仅查询实际需要的属性。这将减少必须在应用程序和数据库之间传输的数据量。
问题是您将可操作ID列表存储到内存中,然后再次使用它进行查询。这意味着EF将把它转换为一个简单的IN查询,并对所有ID进行硬编码。实际上,我甚至怀疑,由于265000条记录的数量太多,它实际上会首先从数据库中获取所有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调用。这意味着idList是EF可以理解的IQueryable,它不会首先执行它,而是在最后一条语句中将它用作子查询或联接,这将具有更好的性能
还考虑如果您实际上需要ItMeExchange实例作为一个整体,或者您可以使用带有选择的投影仅查询实际需要的属性。这将减少应用程序和数据库之间必须传输的数据量。
无需禁用数据库上的LazyLoadingEnabled选项,并使用AsQueryable,以便ID不会出现在内存中。我建议在这种情况下使用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" );
}
不需要在数据库上禁用LazyLoadingEnabled选项,也不需要使用AsQueryable,这样ID就不会出现在内存中。我建议在这种情况下使用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" );
}
你写道:
这两个表之间没有任何关系
很明显,这是有关系的。您希望ItemTranaction.Id.Value有时具有Item.Id的值
您将获得StoreId等于223250的所有项目。从这些项目中获取Id。给我所有的ItemTransactions都有一个Id。值,该值也在获取的Id中
换言之:
要求:给我所有ItemTransactions,其itemTransaction.Id.value的值等于StoreId等于223250的所有项目的Id之一
如果只在一个查询中执行查询,则查询速度会快得多:
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)
简言之:
将itemtransaction与StoreId等于storId的项目联接。
从每个itemTransaction中获取itemTransaction.Id.Value,
从每个项目中获取Id
当这些值相等时,获取itemTransaction和item以创建结果
这个结果就是itemTransaction
您没有这么说,但我认为item.Id是主键。这确保了没有两个项目具有相同的Id,因此所有剩余的itemTransactions都是唯一的。不需要使用Distinct。您写道:
这两个表之间没有任何关系
很明显,这是有关系的。您希望ItemTranaction.Id.Value有时具有Item.Id的值
您将获得StoreId等于223250的所有项目。从这些项目中获取Id。给我所有的ItemTransactions都有一个Id。值,该值也在获取的Id中
换言之:
要求:给我所有ItemTransactions,其itemTransaction.Id.value的值等于StoreId等于223250的所有项目的Id之一
如果只在一个查询中执行查询,则查询速度会快得多:
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)
我
n字:
将itemtransaction与StoreId等于storId的项目联接。
从每个itemTransaction中获取itemTransaction.Id.Value,
从每个项目中获取Id
当这些值相等时,获取itemTransaction和item以创建结果
这个结果就是itemTransaction
您没有这么说,但我认为item.Id是主键。这确保了没有两个项目具有相同的Id,因此所有剩余的itemTransactions都是唯一的。不需要Distinct。1001个ID是否真的存在265000条记录?或者记录中有任何重复?@er mfahhgk确实是265000:/it希望查看表之间的关系。还有一件事,为什么要使用ToList来提取所有列。1001个ID是否真的存在265000条记录?或者记录中有任何重复?@er mfahhgk确实是265000:/it希望查看表之间的关系。还有一件事,为什么要使用ToList来拉所有列。我认为AsQueryable实际上是不必要的。这个查询是IQueryable的,除非你调用ToList。我认为AsQueryable实际上是不必要的。该查询是可查询的,除非您致电ToList。嘿,谢谢您的快速回复!:我明白你打算删除托利斯特。。。这样就减少了数据库的负载,而无需执行项的查询本身。。。但对于交易而言,仍然需要大约65秒的时间…:/这真的很奇怪。。。最终返回了多少条记录?@Marin Zikmund 265757如果只在查询中使用普通计数而不是ToList,需要多长时间?在这种情况下需要421毫秒^^^嘿,谢谢你的快速回复!:我明白你打算删除托利斯特。。。这样就减少了数据库的负载,而无需执行项的查询本身。。。但对于交易而言,仍然需要大约65秒的时间…:/这真的很奇怪。。。最终返回了多少条记录?@Marin Zikmund 265757如果只在查询中使用普通计数而不是ToList,需要多长时间?本例中为421毫秒^^