【发布时间】:2019-09-04 10:21:14
【问题描述】:
我构建了一个简单的 Asp.Net Core MVC 应用程序,用于在我们的 MSSQL 数据库中显示来自视图的数据。从 SSMS 查询此视图时,执行时间平均约为 100 毫秒。当在我的应用程序中执行相同的查询时,执行时间从 ~800 毫秒到 ~1.5 秒不等。
这是来自控制器的 LINQ:
public IActionResult Index()
{
var query =
from p in _context.vWebQuery
where p.Almachine == "600L"
orderby p.Aldatsta
select p;
return View(query);
}
这是实体类:
namespace BetaKestrel2.Models
{
public class vWebQuery
{
public double Wruntim { get; set; }
public short Wper { get; set; }
public double Quantity { get; set; }
[Column("Total Op TIme")]
public double? TotalTime { get; set; }
public string Alwon { get; set; }
public short Alopnum { get; set; }
public string Almachine { get; set; }
public double Alpersta { get; set; }
[DisplayFormat(DataFormatString = "{0:F2}")]
public double Allen { get; set; }
public short Alprevop { get; set; }
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime Aldatsta { get; set; }
public string Altimsta { get; set; }
public string Alstatus { get; set; }
public short Alperno { get; set; }
public string Macid { get; set; }
public string Macdesc { get; set; }
public string Partid { get; set; }
public string Partrevisionid { get; set; }
public string Routingmethod { get; set; }
public double Wqleft { get; set; }
public string Wstate { get; set; }
public string Wdesc { get; set; }
public string Partdesc { get; set; }
public string Toolid { get; set; }
public string Childpartid { get; set; }
public string msection { get; set; }
}
}
还有 DbContext:(使用 .Net Core 3.0 实现 .HasNoKey())
public partial class EfacDBContext : DbContext
{
public EfacDBContext()
{
}
public EfacDBContext(DbContextOptions<EfacDBContext> options)
: base(options)
{
}
public DbSet<vWebQuery> vWebQuery { get; set; }
public DbSet<vGRN> vGRN { get; set; }
public DbSet<vQuotationTracker> vQuotationTracker { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<vWebQuery>(entity =>
{
entity.HasNoKey();
entity.ToTable("vwebquery");
});
还有一个示例 .cshtml 视图:
@model IEnumerable<BetaKestrel2.Models.vWebQuery>
@{
ViewData["Title"] = "600L";
string highlight = "";
}
<h1>Work Centre Plan - @ViewData["Title"]</h1>
<table class="table table-sm table-bordered">
<thead>
<tr>
<th>Works Order</th>
<th>Part Number</th>
<th>Description</th>
<th>Op Number</th>
<th>Quantity</th>
<th>Latest Start Date</th>
<th>Previous Op</th>
<th>Total Op Time (mins)</th>
<th>Status</th>
<th>Qty Left</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
@if (item.Wstate == "COMP")
{
highlight = "background-color: green;";
}
else if (item.Alprevop == 0)
{
highlight = "background-color: yellow;";
}
else
{
highlight = "";
}
<tr style="@highlight">
<td>@Html.DisplayFor(modelItem => item.Alwon)</td>
<td>@Html.DisplayFor(modelItem => item.Partid)</td>
<td>@Html.DisplayFor(modelItem => item.Partdesc)</td>
<td>@Html.DisplayFor(modelItem => item.Alopnum)</td>
<td>@Html.DisplayFor(modelItem => item.Quantity)</td>
<td>@Html.DisplayFor(modelItem => item.Aldatsta)</td>
<td>@Html.DisplayFor(modelItem => item.Alprevop)</td>
<td>@Html.DisplayFor(modelItem => item.TotalTime)</td>
<td>@Html.DisplayFor(modelItem => item.Wstate)</td>
<td>@Html.DisplayFor(modelItem => item.Wqleft)</td>
</tr>
}
</tbody>
</table>
EF Core 转换为以下 SQL
SELECT
[v].[Aldatsta]
,[v].[Allen]
,[v].[Almachine]
,[v].[Alopnum]
,[v].[Alperno]
,[v].[Alpersta]
,[v].[Alprevop]
,[v].[Alstatus]
,[v].[Altimsta]
,[v].[Alwon]
,[v].[Childpartid]
,[v].[Macdesc]
,[v].[Macid]
,[v].[Partdesc]
,[v].[Partid]
,[v].[Partrevisionid]
,[v].[Quantity]
,[v].[Routingmethod]
,[v].[Toolid]
,[v].[Total Op TIme]
,[v].[Wdesc]
,[v].[Wper]
,[v].[Wqleft]
,[v].[Wruntim]
,[v].[Wstate]
,[v].[msection]
FROM [vwebquery] AS [v]
WHERE
[v].[Almachine] = N'BENDD'
AND [v].[Almachine] IS NOT NULL
ORDER BY
[v].[Aldatsta]
结果:
信息:Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[4] Executed ViewResult - 视图索引在 1540.6805000000002ms 内执行。
信息:Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] 在 1541.4348ms 内执行动作 BetaKestrel2.Controllers.BenddController.Index (BetaKestrel2)
信息:Microsoft.AspNetCore.Routing.EndpointMiddleware[1] 执行的端点“BetaKestrel2.Controllers.BenddController.Index (BetaKestrel2)”
信息:Microsoft.AspNetCore.Hosting.Diagnostics[2] 请求在 1541.8467 毫秒内完成 200 text/html;字符集=utf-8
而在 SSMS 中
总执行时间 124 毫秒
我尝试了 AsNoTracking() 并没有什么不同。你最后的评论让我很好奇。查询返回了 291 行,所以我尝试了 .Take(5) 并且执行时间下降到 24ms。 真的只是我的 foreach 循环在视图中的迭代占用了所有时间?
【问题讨论】:
-
嗯,首先,该数字是您返回响应的总执行时间,而不仅仅是运行查询所需的时间。还有许多其他因素可能会减慢响应速度,但我们无法查看您的任何其他代码。
-
抱歉,我对 OOP 还很陌生,但我仍然对这一切有所了解。为了更清楚,我编辑了我的问题。
-
看我的回答,你测量的是不一样的东西,只测量查询的执行而不是额外的 OOP 和渲染管道。是的 1v1 会更慢,但不如 EF 给你的有用性那么多。您可能花费的时间可能不到 3 毫秒(可能为什么会更少)
-
刚刚看到你的更新。具有这么多字段的 291 行(20 个)对于所有 291 个字段应该像 24 毫秒一样快,所以我猜它可能与 DisplayFormat 和 Column 有关,其中一列是否包含大量文本......比如 500加字符..检查字段中数据的大小..
-
wdesc 是 nvarchar(255),但该列中的最高长度是 41 个字符
标签: asp.net-core entity-framework-core