我在 Windows 2008R2 的 ASP.NET 上运行 Entity Framework 4.1 和 .NET 4.5。我正在使用 EF 代码优先连接到 SQL Server 2008R2,并执行一个相当复杂的 LINQ 查询,但结果只是一个 Count()。
我已经在两台不同的网络服务器上重现了这个问题,但只有一个数据库(当然是生产环境)。它最近开始发生,没有在 Web 或数据库端更改应用程序、数据库结构或服务器。
我的问题是在某些情况下执行查询会花费大量时间(接近 4 分钟)。我可以采用从 SQL Profiler 中提取的实际查询,并在大约 1 秒内在 SSMS 中执行。这对我来说是一致且可重现的,但是如果我将其中一个参数(“2015-01-22 之后的日期”参数)的值更改为更早的值,例如 2015-01-01,或更晚的值,例如 2015-02- 01,它在 EF 中运行良好。但是我把它放回 2015-01-22 又变慢了。我可以一遍又一遍地重复这个。
然后我可以在 EF 中运行类似但不相关的查询,然后返回到原始查询,这次它运行良好 - 与以前完全相同的查询。但如果我打开一个新的浏览器,这个循环又会重新开始。那部分也没有意义 - 我们没有做任何事情来保留用户 session 中的数据上下文,所以我不知道为什么它会起作用。
但这一切都告诉我数据本身没问题。
在 Profiler 中,当查询正常运行时,大约需要一两秒钟,并显示大约 2,000,000 次读取和大约 2,000 次 CPU 读取。当它运行缓慢时,需要 3.5 分钟,并且值为 300,000,000 和 200,000 - 因此读取大约高出 150 倍,CPU 高出 100 倍。同样,对于相同的 SQL 语句。
关于 EF 可能以不同方式执行哪些不会显示在查询文本中的任何建议?是否存在某种隐藏的连接属性,在某些情况下可能会导致不同的执行计划?
编辑
EF 构建的查询是其中一种查询,它使用文本中包含的参数构建一个巨大的字符串,而不是作为 SQL 参数:
exec sp_executesql
N'SELECT [GroupBy1].[A1] AS [C1]
FROM (
SELECT COUNT(1) AS [A1]
...
AND ([Extent1].[Added_Time] >= convert(datetime2, ''2015-01-22 00:00:00.0000000'', 121))
...
) AS [GroupBy1]'
编辑
我没有添加这个作为答案,因为它实际上并没有解决根本问题,但这最终通过重建索引和重新计算统计信息得到解决。这样做的时间比平时更长,似乎已经解决了导致问题的所有问题。
我会继续阅读此处的一些链接,以防再次发生这种情况,但由于它现在一切正常且无法重现,我不知道我是否能确切地知道它在做什么。
感谢所有的想法。
最佳答案
我最近有一个非常相似的场景,一个查询将运行得非常快,直接在数据库中执行它,但使用 EF(在我的例子中是版本 5)的性能很糟糕。这不是网络问题,差异是 4 毫秒到 10 分钟。
问题最终变成了映射问题。我有一个映射到 NVARCHAR 的列,而它在数据库中是 VARCHAR。看起来无伤大雅,但这导致了数据库中的隐式转换,这完全破坏了性能。
我不完全确定为什么会发生这种情况,但根据我所做的测试,这导致数据库执行索引扫描而不是索引查找,显然它们在性能方面非常不同。
我写了关于这个的博客 here (免责声明:它是葡萄牙语),但后来我发现 Jimmy Bogard 在 post 中描述了这个确切的问题。从 2012 年开始,我建议您检查一下。
由于您的查询中确实有一个转换,我会说从那里开始。仔细检查所有列映射并检查表列和实体属性之间的差异。避免在查询中进行隐式转换。
如果可以,请检查您的 execution plan要发现任何不一致之处,请注意黄色警告三角形,它可能表示与进行隐式转换有关的类似问题:
我希望这能以某种方式帮助你,这对我们来说是一个非常困难的问题,但最终是有道理的。
关于c# - Entity Framework 的查询执行速度极慢且效率低下,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29242469/
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json