【发布时间】:2018-09-27 23:12:29
【问题描述】:
在将新表加入到 LINQ 查询后,我遇到了问题。实际上,它返回了我期望的数据,并且在测试中运行得很快。但是,似乎随着更多用户连接到数据库,查询开始超时。例如,在生产的前 30 或 45 分钟一切正常,但在上午 8:20 左右,它开始超时。同样,我认为这是由于整体上数据库的使用量增加所致。
这里有一点关于 ASP.NET MVC (5) 应用程序的背景知识,以防万一。
- 用户向我们的诊所提交了转诊
- 推荐包含一个或多个订单
- 如果提供的人员信息与现有人员不匹配,我会做几件事,包括在“订单”表中插入记录(推荐中选择的每个订单对应一条记录)。
- 如果提供的人员信息与我们系统中的现有人员匹配,则我将推荐“保留”在队列中,直到通过将其与现有人员匹配或覆盖它并在其中创建新人员手动解决它系统。此时,推荐中选择的任何订单都会在表格中创建。
因此,在这种情况下要考虑的两个主要表是“referral”(在我的代码中命名为“Referrals”)和“order”(在我的代码中命名为“ReferralPPA”)表。到目前为止,我不需要将相关查询从 Referrals 表链接到 ReferralPPA 表(将查询链接到 ReferralPPA 表似乎是在数据库/应用程序使用量增加时会减慢查询速度的原因)。
此外,如果这有帮助,推荐是由外部用户输入的,而我从推荐中创建的订单在一个单独的应用程序中工作,内部员工作为用户,尽管它们都在同一个数据库中。 ReferralPPA 表可能在一天中的大部分时间都被大量使用。
查询如下所示:
IQueryable<ReferralListViewModel> referrals = (from r in _context.Referrals
join cu in _context.ClinicUsers on r.ClinicId equals cu.ClinicId
/* Here is the seemingly problematic join */
from ppa in _context.ReferralPPAs
.Where(p => p.ref_id == r.seq_no.ToString())
.DefaultIfEmpty()
/* End of seemingly problematic join */
join ec in _context.EnrolledClinics on r.ClinicId equals ec.ClinicId
join pm in _context.ProviderMasters on ec.ClinicId equals pm.ClinicId
join ml in _context.MasterLists on pm.HealthSystemGuid equals ml.Id
join au in _context.Users on r.ApplicationUserId equals au.Id
where cu.UserId == userId
select new ReferralListViewModel()
{
ClinicName = pm.Description,
ClinicId = r.ClinicId,
ReferralId = r.seq_no,
EnteredBy = (au.FirstName ?? string.Empty) + " " + (au.LastName ?? string.Empty),
PatientName = (r.LastName ?? string.Empty) + ", " + (r.FirstName ?? string.Empty),
DateEntered = r.create_timestamp,
Status = ppa != null ? ppa.Status : string.Empty
});
因此,如果没有我上面提到的连接,我不会遇到任何问题,而且它运行得非常快。添加连接似乎也很快,直到系统上有一定数量的用户(至少这是我的假设)。
我还尝试了其他一些方法来帮助提高性能并防止出现问题。我将 UseDatabaseNullSemantics 设置为 True,这似乎对整体性能产生了很大影响。
_context.Configuration.UseDatabaseNullSemantics = true;
我还想知道问题是否是对相关表的锁定问题,因此我尝试将查询包装在事务中以执行 ReadUncommitted。
using (var transaction = _context.Database.BeginTransaction(System.Data.IsolationLevel.ReadUncommitted))
{
//query
}
同样,虽然这稍微提高了整体性能,但似乎并没有最终解决问题。
如果有人对如何解决这个问题有任何想法、想法或建议,我将不胜感激。
【问题讨论】:
-
我对这种形式的 LINQ 不是很熟悉,但是你为什么要做一个
.Where而不是另一个加入呢?它没有左连接吗?其他想法是您似乎正在通过调用.ToString来更改数据类型,这会很快变得非常昂贵 -
不要害怕将其中一些复杂的 sql 查询作为 procs 放入数据库中。由于已经建立了执行计划,它们可以被预编译并运行得更快。仅仅因为您可以使用 Linq 构建复杂的查询并不意味着是最好的方法。
-
为了获得 LEFT OUTER JOIN(这是我在这里需要的),您需要在加入时调用 DefaultIfEmpty()。这是似乎有效的语法示例之一。关于 .ToString(),我知道这很昂贵,但这是在我们的系统中完成的,不管你信不信,这不是问题。我什至在另一个查询中执行此操作,该查询在同一页面加载时被调用,并且运行速度很快。感谢您的参与!
-
@Kevbo - 如果我不在控制器中进行搜索、排序和分页,我可以这样做,这个查询就在里面。这只是核心查询,但如果使用了这些功能中的任何一个,就会被修改。
-
没问题,这就是我们在这里的原因 :) 现在,问题是没有官方方法可以删除演员表。我正在考虑一些骇客,当有具体的事情时会告诉你。
标签: c# sql-server asp.net-mvc entity-framework linq