对 RavenDB 随机缓慢进行故障排除
本文关键字:故障 排除 缓慢 RavenDB 随机 | 更新日期: 2023-09-27 17:56:14
我有一个使用RavenDB的WPF应用程序。在其中一个窗口中,我可以反复点击"刷新"按钮来更新网格。每次刷新都会导致 RavenDB 查询。奇怪的是,时不时地查询会花费很长时间。例如,我可以连续点击七次"刷新"按钮,网格将在不到一秒钟的时间内刷新。然后,在第 8 次尝试时,将需要 12 秒。然后,我可以再按 Refresh 11 次,它再次快速运行,但在第 12 次时,它又需要 12 秒。这种方式非常一致。每次延迟似乎总是需要 12 秒。什么?
下面是查询:
IQueryable<EntityBase> installationSummaries =
QueryAndSetEtags(session => session.Query<InstallationSummary>()
.Include(x => x.ApplicationServerId)
.Include(x => x.ApplicationWithOverrideVariableGroup.ApplicationId)
.Include(x => x.ApplicationWithOverrideVariableGroup.CustomVariableGroupId)
.Customize(x => x.WaitForNonStaleResults())
.OrderByDescending(summary => summary.InstallationStartUtc)
.Take(numberToRetrieve)
);
HydrateInstallationSummaries(installationSummaries);
return installationSummaries.AsEnumerable().Cast<InstallationSummary>();
延迟始终位于以下代码行上(entityBases 是上述查询的返回值):
List<EntityBase> entityBaseList = entityBases.ToList();
在 RavenDB 中对此类内容进行故障排除的正确方法是什么?我不确定接下来要尝试什么。
注意:此代码很久没有更改了。我现在使用的是RavenDB 960。这在RavenDB 573中从未发生过。
编辑 -- 用于显示此查询周围发生的其他情况的附加代码。
private static void HydrateInstallationSummaries(IQueryable<EntityBase> installationSummaries)
{
// Note: We use session.Load() below so that we get the information from the session, and not another trip to the DB.
foreach (InstallationSummary summary in installationSummaries)
{
HydrateInstallationSummary(summary);
}
}
private static void HydrateInstallationSummary(InstallationSummary summary)
{
if (summary == null) { return; }
summary.ApplicationServer =
QuerySingleResultAndSetEtag(session => session.Load<ApplicationServer>(summary.ApplicationServerId))
as ApplicationServer;
summary.ApplicationWithOverrideVariableGroup.Application =
QuerySingleResultAndSetEtag(session => session.Load<Application>(summary.ApplicationWithOverrideVariableGroup.ApplicationId))
as Application;
if (summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId == null) { return; }
summary.ApplicationWithOverrideVariableGroup.CustomVariableGroup =
QuerySingleResultAndSetEtag(session =>
{
if (session.Advanced.IsLoaded(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId))
{
return session.Load<CustomVariableGroup>(summary.ApplicationWithOverrideVariableGroup.CustomVariableGroupId);
}
return null; // Note: We can be missing a custom variable in the session because someone deleted it.
;
})
as CustomVariableGroup;
}
这是QueryAndSetEtags():
protected static IQueryable<EntityBase> QueryAndSetEtags(Func<IDocumentSession, IQueryable<EntityBase>> func)
{
if (func == null) { throw new ArgumentNullException("func"); }
IQueryable<EntityBase> entities = func.Invoke(_session);
SetEtags(entities, _session);
return entities;
}
protected static void SetEtags(IEnumerable<EntityBase> entityBases, IDocumentSession session)
{
foreach (EntityBase entityBase in entityBases)
{
SetEtag(entityBase, session);
}
}
protected static void SetEtag(EntityBase entityBase, IDocumentSession session)
{
entityBase.Etag = (Guid)session.Advanced.GetEtagFor(entityBase);
}
在该示例中,您有很多自定义代码,因此很难确切知道发生了什么。 但我很确定问题出在这条线上:
.Customize(x => x.WaitForNonStaleResults())
这不是您在生产查询中想要的内容。 它是单元测试的主要内容。
尝试完全删除该行,或者如果您确实需要等待,请改为指定一个截止点,例如:
.Customize(x => x.WaitForNonStaleResultsAsOfNow())
如果可能,请考虑升级到 RavenDB 2.0。 它具有更好的性能和功能。