Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 与硬编码整数值相比,使用整数变量时Linq to SQL查询速度非常慢_C#_.net_Entity Framework_Linq To Sql_Ienumerable - Fatal编程技术网

C# 与硬编码整数值相比,使用整数变量时Linq to SQL查询速度非常慢

C# 与硬编码整数值相比,使用整数变量时Linq to SQL查询速度非常慢,c#,.net,entity-framework,linq-to-sql,ienumerable,C#,.net,Entity Framework,Linq To Sql,Ienumerable,我有一个大约需要10秒才能执行的查询 奇怪的是,如果我用硬编码的整数(如3)替换“machineNo”参数,查询需要一秒钟的时间。这是迄今为止我遇到的最不寻常的性能问题 public static IEnumerable<vwJobAppointment> GetAllJobs(int machineNo) { var db = new DbContext(); IEnumerable<vwJobAppointment> list; list =

我有一个大约需要10秒才能执行的查询

奇怪的是,如果我用硬编码的整数(如3)替换“machineNo”参数,查询需要一秒钟的时间。这是迄今为止我遇到的最不寻常的性能问题

public static IEnumerable<vwJobAppointment> GetAllJobs(int machineNo)
{
    var db = new DbContext();
    IEnumerable<vwJobAppointment> list;
    list = db.vwJobAppointments.Where(a => a.ResourceId == (machineNo)).AsNoTracking().ToList();
    return list;
}
公共静态IEnumerable GetAllJobs(int-machineNo)
{
var db=new DbContext();
i可数列表;
list=db.vwjobAppoints.Where(a=>a.ResourceId==(machineNo)).AsNoTracking().ToList();
退货清单;
}
查询需要10秒钟+

public static IEnumerable<vwJobAppointment> GetAllJobs(int machineNo)
{
    var db = new DbContext();
    IEnumerable<vwJobAppointment> list;
    list = db.vwJobAppointments.Where(a => a.ResourceId == (3)).AsNoTracking().ToList();
    return list;
}
公共静态IEnumerable GetAllJobs(int-machineNo)
{
var db=new DbContext();
i可数列表;
list=db.vwjobAppoints.Where(a=>a.ResourceId==(3)).AsNoTracking().ToList();
退货清单;
}
此查询耗时不到一秒


有什么想法吗?我将Entity Framework 5与SQL 2008数据库一起使用

这听起来像是参数嗅探;i、 e.典型的参数化计划缓存问题,其中使用初始示例参数值生成查询计划,结果表明该参数值需要与其他一些值非常不同的计划。如果数据是倾斜的,这是非常常见的-例如,一些值将有3个匹配项,而其他值将有300000个匹配项。这通常是在
选项(针对…未知进行优化)
提示起作用时发生的,但这需要您的ORM能够指定此提示,或者您可以手动编写SQL。

EF查询被转换为SQL。SQL使用查询计划来优化查询。变量往往会使过程慢得多。在某些情况下,如果在临时表中选择输入变量,并在通常检查输入变量的位置加入此表,则可以克服此问题。该过程的另一个好处是可以强制执行查询计划。我建议:


  • 创建将资源ID作为输入的存储过程
  • 尝试在临时表中选择输入变量并连接该变量
  • 如果这无助于强制执行查询计划

    • 您可以稍微优化一下where表达式。在这种情况下,可以将参数变量重新指定给局部变量。在我的测试中,我有三种方法:

      // Execution time: 00:00:00.0140118
      public static IEnumerable<myClass> GetAllJobs(int machineNo)
      {
          var db = new DbContext();
          IEnumerable<myClass> list;
          list = db.vwJobAppointments.Where(a => a.ResourceId == (machineNo)).ToList();
          return list;
      }
      
      // Execution time: 00:00:00.0019991
      public static IEnumerable<myClass> GetAllJobs2(int machineNo)
      {
          var db = new DbContext();
          IEnumerable<myClass> list;
          list = db.vwJobAppointments.Where(a => a.ResourceId == 55).ToList();
          return list;
      }
      
      // Execution time: 00:00:00.0010013
      public static IEnumerable<myClass> GetAllJobs3(int machineNo)
      {
          int machineNo2 = machineNo;
          var db = new DbContext();
          IEnumerable<myClass> list;
          list = db.vwJobAppointments.Where(a => a.ResourceId == (machineNo2)).ToList();
          return list;
      }
      
      //执行时间:00:00:00.01401118
      公共静态IEnumerable GetAllJobs(int-machineNo)
      {
      var db=new DbContext();
      i可数列表;
      list=db.vwjobAppoints.Where(a=>a.ResourceId==(machineNo)).ToList();
      退货清单;
      }
      //执行时间:00:00:00.0019991
      公共静态IEnumerable GetAllJobs2(int-machineNo)
      {
      var db=new DbContext();
      i可数列表;
      list=db.vwjobAppoints.Where(a=>a.ResourceId==55.ToList();
      退货清单;
      }
      //执行时间:00:00:00.0013
      公共静态IEnumerable GetAllJobs3(int-machineNo)
      {
      int machineNo2=machineNo;
      var db=new DbContext();
      i可数列表;
      list=db.vwjobAppoints.Where(a=>a.ResourceId==(machineNo2)).ToList();
      退货清单;
      }
      
      我认为第二个查询运行得更快,因为当您使用machineNo变量运行第一个查询时,查询计划在缓存中。传递的
      3
      值是否与
      machineNo
      相同?还是一个不同的值?相同的值。。。因此,返回的数据集完全相同应用程序启动时,这两个查询都会作为第一个查询进行测试,因此不应成为缓存问题“第一个查询”不仅取决于应用程序-实际数据库也有发言权,而且它可以基于参数嗅探缓存极不合适的计划。“变量往往会使过程慢得多”-那是。。。不是真的;“在某些情况下,如果您在临时表中选择输入变量并将此表连接到您通常会对照输入变量进行检查的位置,您可以克服这一问题。”-这也是可疑的;在某些情况下,临时表(或表变量)可能会有所帮助,但这还远远不是最需要尝试的事情;“该过程的另一个好处是,您可以强制执行查询计划。”—您无论如何都可以这样做—您这样做的能力不会改变“创建一个将资源ID作为输入的存储过程”——这是一些问题的解决方案,但不是这个问题;这里的查询计划并不关心它是否是存储过程。90%以上的时候我看到人们说“使用存储过程”,这与问题完全无关。我只是建议创建一个存储过程,以便能够完成我建议的其他事情。或者是否有可能从表上的EF select强制执行查询计划?关键是,在存储过程和EF生成的SQL之间存在中间地带;您可以非常轻松地通过EF运行特设SQL,并且使用特设参数化SQL,您可以完成存储过程中的所有操作,包括查询hints@NeilHobson你需要谨慎;对于参数嗅探,强制重新编译(这是您在这里所做的)将暂时“修复”它是很常见的,但这也可能意味着您已经导致它-现在-使用它为其他值生成的计划,一个足够正常的值。它可以在任何时候恢复。除非您已经解决了实际问题(这一点:转移到存储过程是不行的),否则您所做的一切就是给它一个机会,然后重新忽略实际问题。这会(也会)再次伤害你。