我目前有一个系统,用户可以注册并下注足球比赛的分数。 现在我有超过2万用户,超过300万投注。每周我都要生成一个排名,所以我有一个查询,在内存中加载所有用户的赌注就像这样:
from u in context.Set<User>().include("Bets").OrderByDescending(u => u.Points)
select u
其中积分是每次猜测所获得的积分之和。 在此查询结束后,我将用户及其位置保存在另一个表上以构建我的排名。
事实是,这个查询消耗了太多内存!超过4gb !!!我需要所有用户和赌注来计算排名。我尝试的第一个选择是:创建另一个表来存储用户及其点。我会迭代这个查询,每次加载500个用户,而不是计算和保存,但我仍然坚持内存问题:
int page = 0;
int step = 500;
while (page * step < count)
{
foreach (var u in context.Set<User>()
.Skip(page * step)
.Take(step).ToList())
{
//Saves in another table
}
page++;
}
//Sorts based on the data from this other table
由于这不起作用,我放弃了,然后我尝试做这样的事情:
var users = (from u in context.Set<User>().Include("Bets")
select u).ToList();
context.Dispose()
var sortedUsers = from u in users.OrderByDescending(u => u.Points)
select u;
但也没解决......
我猜问题是关于保存所有跟踪信息的上下文。 有人有任何线索吗?如何使用EF 4.1处理大量数据?
由于
我注意到的另一件事。 假设我有用户A和用户B, 每个人只有1次投注到同一场比赛,我希望有类似的东西:
User A ---> Bet
\
Match
/
User B ---> Bet
但我有两个不同的Match实例具有相同的数据。 有没有办法避免这种情况?
为什么我不愿意将其放在存储过程中:
排名基于猜测,并且有关于此排序的一些规则。
用户有N个投注。每个赌注都与一个有分数的游戏相关联。
第一个分类标准是分数。所以我需要计算每次下注的积分(每个用户有大约200个投注,并且在锦标赛结束时将有大约300个投注)。那是第一次加入。
要计算每次下注的积分,我需要比赛的最终得分。那是另一个加入。
在得到每个赌注的点数之和(大约有10个条件)并按照它排序后,我仍然需要根据以下内容进行排序:
没有。正确的赌注, 获胜者被猜到的投注数量, 猜测一个分数的投注数, 最后一次下注的日期, 注册日期。
所以这是一个大约6个标准,大约3个连接和大量逻辑的巨大排序。在LINQ中计算这个非常简单,如果我必须将它放在SP上,则需要花费很多时间,而且更容易出错。 (从未在SP中尝试过TDD甚至单元测试......这个排名测试了一切)
答案 0 :(得分:3)
我同意@Allan,理想情况下,这将在存储过程中完成。如果您可以发布计算的详细信息,也许其他人可以建议在存储过程中执行此操作的方法。
如果你想保持原样,你可以尝试一些事情:
context.Set<User>().AsNoTracking() // etc
User
或Bet
类具有许多您不需要进行计算的属性,请将它们投影为只具有所需属性的匿名类型。希望这会有所帮助,如果你尝试AsNoTracking
,我会很想知道它有多大差异。
答案 1 :(得分:1)
Dude我认为如果你只是在存储过程中而不是在C#代码上计算这些数据会更明智。如果可以通过使用现有数据计算这些数据,则无需保存这些数据。将它们保存在另一个表中会导致数据冗余,并且会违反良好的数据库规范化规则。