我在ASP.NET MVC应用程序中工作,并有两个不同的连接(数据库)。这就像用户进行一些小型考试的应用程序。在一个页面上,我必须向用户显示所有详细信息的考试/活动:何时,哪些结果以及有关活动/考试的所有详细信息。在红色数据库中只有关于结果,时间,用户和activityid的信息 - 因此您可以在另一个(蓝色)数据库中获取该跟踪的活动。每项活动最多可以完成5次。
我尝试了几种不同的查询,但性能非常非常慢。您有什么想法我如何解决此查询,用户不必在页面上等待10秒钟?
谢谢!
修改
跟踪表(db1,表1)现在有1732982条记录,并且它总是在增长,因为用户可以随时进行检查。目前有1832项活动来自110课。
下面详细的数据库图片(这是我得到的,所以我必须使用它但我可以根据需要更改ids / pk / fk - 或者更改我需要的任何内容,但它必须保留在两个不同的数据库中):
以下是用于获取一个用户的结果的代码。 UserId像函数中的参数一样发送,并在此代码中使用。
IList<TrackingCustomModel> result = new List<TrackingCustomModel>();
using (DATA.examContent.Model ctc = new DATA.examContent.Model()) //first database (activities, lessons)
{
using (Model ctx = new Model()) //this is second database (tracking)
{
// Get all Activities
IList<Activity> ac = ctc.Activity.Include("Lesson").ToList();
char[] trimChars = { '0' };
IEnumerable<TrackingCustomModel> q;
q = from a in ac
select new TrackingCustomModel
{
ActivityId = a.Id,
LessonCode = a.Lesson.Code.TrimStart(trimChars),
ActivityCode = a.Code.TrimStart(trimChars),
ActivityHead = a.Head.Trim()
};
IList<TrackingCustomModel> add = q.ToList<TrackingCustomModel>();
// Get all Trackings for userId
IList<Tracking> tr = ctx.Tracking.Where(t => t.UserId == userId).ToList();
// Join Activites with Tracking of User, and Calculate Scores
var s = from a in add
join t in tr on a.ActivityId equals t.ActivityId
orderby t.Timestamp descending
select new TrackingCustomModel
{
ActivityId = a.ActivityId,
LessonCode = a.LessonCode,
ActivityCode = a.ActivityCode,
ActivityHead = a.ActivityHead,
Timestamp = DefaultHelper.AdjustDateToLocalTimezone(t.Timestamp),
ActivityHits = t.ActivityHits,
ActivityMistakes = t.ActivityMistakes,
ActivityScore = (t.ActivityHits + t.ActivityMistakes) > 0 ? (String.Format("{0:0%}", (Decimal.Divide(t.ActivityHits, (t.ActivityHits + t.ActivityMistakes))))).ToString() : null
};
// Group the results by Activity and calculate the Activity average
var group = from t in s
group t by t.ActivityId into g
select g;
foreach (IGrouping<Guid, TrackingCustomModel> g in group)
{
TrackingCustomModel thc = (from t in g
where t.ActivityId == g.Key
select t).FirstOrDefault();
IList<TrackingCustomModel> multipleTry = (from d in s
where d.ActivityId == g.Key
select d).ToList();
if (multipleTry.Count > 1)
{
thc.ActivityDone = multipleTry.Count.ToString();
Decimal scoreAsDecimal;
Decimal averageScore = 0;
foreach (TrackingCustomModel t in multipleTry)
{
if (t.ActivityHits != 0)
{
scoreAsDecimal = (Decimal.Divide(t.ActivityHits, (t.ActivityHits + t.ActivityMistakes)));
averageScore += scoreAsDecimal;
}
}
averageScore /= multipleTry.Count;
if (averageScore != 0)
{
thc.AverageScore = String.Format("{0:0%}", averageScore).ToString();
}
else
{
thc.AverageScore = "";
}
}
else
{
thc.ActivityDone = "";
}
result.Add(thc);
}
}
}
return result;
答案 0 :(得分:0)
确保索引where where子句。例如。 UserId,可能包括DateTime?
确保将Activity.ActiviyID编入索引,因为这是您在第二个查询中应该搜索的内容。
课程信息应该由Lesson.LessonID搜索,应该编入索引
如果使用EF,请执行
var res = Activities
.Include(x => x.Lesson)
.Where(x => activityIds.Contains(x.AcitivityID))
.ToList()
从活动中将课程带入一个电话中。
否则如果使用自定义SQL,请添加连接,例如
SELECT * FROM Table1 a JOIN Table2 b ON a.LessonID = b.LessonID
并确保正确映射。
不确定数据库中有多少数据,但请注意代码中的以下查询:
IList<Activity> ac = ctc.Activity.Include("Lesson").ToList();
.Include("Lesson")
会复制具有相同ID的课程,可能导致无法获取大量数据e.g。如果您有1节课,但有50个活动,那么您将为这50个活动中的每个活动检索一个单独的课程实例(即使它们是相同的)。