В настоящее время у меня есть система, в которой пользователи могут регистрироваться и ставить оценки в футбольных играх.
Прямо сейчас у меня более 20 тысяч пользователей и более 3 миллионов ставок. Каждую неделю мне приходится генерировать рейтинг, поэтому у меня есть запрос, который загружает в память всех пользователей со ставками, например:
from u in context.Set<User>().include("Bets").OrderByDescending(u => u.Points)
select u
Где Баллы - это сумма баллов, полученных за каждое предположение.
После того, как этот запрос закончен, я сохраняю пользователя и его позицию на другом столе для построения моего рейтинга.
Дело в том, что этот запрос потребляет слишком много памяти! Более 4 ГБ! И мне нужны все пользователи и ставки для расчета рейтинга.
Первая альтернатива, которую я попробовал, была: Создайте другую таблицу для хранения пользователя и его точек. Я бы повторил этот запрос, загружая 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, это заняло бы много времени и больше подвержено ошибкам. (Никогда не пробовал TDD и даже модульное тестирование в SP ... В этом рейтинге есть тесты для всего)