使用字段构建EF查询的巨大性能差异

时间:2015-09-02 12:47:39

标签: entity-framework

通过使用字段构建查询,我注意到了一些巨大的性能差异。例如:

效果字段:数据库读取:21118,持续时间:156

表现没有字段:数据库读取:8113,持续时间: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版本信息

1 个答案:

答案 0 :(得分:1)

  

为什么存在这种巨大的性能差异

关于为什么或为什么不关于第三方组件的实现的问题总是很难通过"来解决,因为"。

显然,当涉及变量而不是值时,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声明。