通过使用字段来构建查询,我注意到一些巨大的性能差异。例如:
性能与字段:DB读取:21118,持续时间:156
不带字段的性能:DB Reads: 8113, Duration: 29
带有字段的代码示例
var newStatus = OrderStatus.New.ToString();
var inProgressStatus = OrderStatus.InProgress.ToString();
var inReview = OrderStatus.InReview.ToString();
var data = ctx.COM_Order
.Select(o => new QueryModel
{
Order = o,
SortPrio = (o.COM_OrderStatus.StatusName == newStatus
|| o.COM_OrderStatus.StatusName == inProgressStatus
|| o.COM_OrderStatus.StatusName == inReview
? 1 : 2),
ClassNames = o.COM_OrderItem
.Join(CMS_Tree, orderItem => orderItem.OrderItemSKUID, tree => tree.NodeSKUID,
(oi, t) => t.CMS_Class.ClassName),
UDM_LegalData = UDM_LegalData.Where(d => o.COM_Customer.CustomerID == d.CustomerID).FirstOrDefault(),
UDM_OrderStatusHistory = UDM_OrderStatusHistory.Where(h => h.OrderId == o.OrderID),
});
SQL输出:http://pastie.org/10391835
代码示例不包含字段
var data = ctx.COM_Order
.Select(o => new QueryModel
{
Order = o,
SortPrio = (o.COM_OrderStatus.StatusName == "New"
|| o.COM_OrderStatus.StatusName == "InProgress"
|| o.COM_OrderStatus.StatusName == "InReview"
? 1 : 2),
ClassNames = o.COM_OrderItem
.Join(CMS_Tree, orderItem => orderItem.OrderItemSKUID, tree => tree.NodeSKUID,
(oi, t) => t.CMS_Class.ClassName),
UDM_LegalData = UDM_LegalData.Where(d => o.COM_Customer.CustomerID == d.CustomerID).FirstOrDefault(),
UDM_OrderStatusHistory = UDM_OrderStatusHistory.Where(h => h.OrderId == o.OrderID),
});
SQL输出:http://pastie.org/10391839
为什么有这么大的性能差异,我可以使用字段/枚举没有性能缺陷吗?
感谢- 已测试EF版本6.0.2和6.1.3
更新1
- 添加sql输出
- 将示例查询更新为"完整的EF查询"(我无法再现降级示例查询的性能差异)
更新2
- 新增EF版本信息
为什么有这么大的性能差异
关于为什么或为什么不使用第三方组件的问题总是很难用"因为"来回答。
显然,涉及变量的SQL生成与涉及值的SQL生成不同。我不知道为什么,我也不想去猜。
我所知道的是,你可以使用Contains
:
var statuses = new[] { newStatus, inProgressStatus, inReview };
var data = ctx.COM_Order
.Select(o => new QueryModel
{
Order = o,
SortPrio = statusses.Contains(o.COM_OrderStatus.StatusName) ? 1 : 2),
...
这将始终转换为IN
语句。