我们最近开始在C#中开发应用程序,并决定尝试使用代码优先方法来处理持久性的Entity Framework 6.1.3。数据存储在本地服务器上运行的SQL Server Express 2012实例中。该应用程序仍然很小。目前我们只持有两个POCO并在数据库中有两个表:一个有5个字段(大约10行数据),另一个有4个字段(2行)。
当Entity Framework处理第一个查询并且后续查询非常快时,我们遇到了3秒的延迟。经过一番搜索,我们发现这对于实体框架来说是正常的,所以尽管对于这么小的数据库来说这似乎太过分了,但我们一直在处理它。
今天做了一些工作,其中没有一个与持久性有关,突然我发现第一个查询只花了四分之一秒才能运行。在我所做的更改中,我无法看到任何显而易见的内容,因此我将其上传到源代码管理中,并要求我的同事下载所有内容。当他在他的计算机上构建并运行它时,第一次查询仍需要3秒钟。我已经编译了应用程序,在两台测试计算机上试用了它们,它们经历了最初的3秒延迟。
问题与计算机/操作系统之间似乎没有相关性。我的电脑运行的是Windows 7 SP1 x64。我的同事的开发计算机正在运行Windows 10 x64。另外两台测试计算机正在运行Windows 7 SP1 x86。它们都是类似的规格(Core i5,4GB / 8GB RAM)。
在我对延迟的研究中,我发现你可以做几件事来提高性能(预生成视图等),但我没有做过这些。我没有安装任何东西或对我的系统进行任何更改,但我认为可能在后台安装了更新。数据库服务器或数据库本身或POCO中没有任何更改。我们都在同一台服务器上连接到同一个数据库。
这提出了一些明显相关的问题。如果它可能在四分之一秒内启动,为什么到现在为止需要3秒?我的计算机上发生了什么事情突然改善了性能,我怎样才能在其他仍然很慢的计算机上复制它?
有人可以提供任何建议吗?
修改
我打开了登录Entity Framework,看看正在运行什么查询以及他们花了多长时间。在第一个之前,为了测试目的,只运行查询,EF运行3个查询来进行迁移。生成的用于检索我的数据的查询如下:
SELECT
[Extent1].[AccountStatusId] AS [AccountStatusId],
[Extent1].[Name] AS [Name],
[Extent1].[Description] AS [Description],
[Extent1].[SortOrder] AS [SortOrder]
FROM [dbo].[AccountStatus] AS [Extent1]
-- Executing at 28/01/2016 20:55:16 +00:00
-- Completed in 0 ms with result: SqlDataReader
正如你所看到的那样,它运行得非常快,考虑到该表中只有2条记录,这并不奇怪。 3个迁移查询和我的查询在我的计算机和我的同事的计算机上总共运行不超过5毫秒。
将该查询复制到SSMS并从其他各种计算机运行它会产生相同的结果。它快速没有记录所花费的时间。它当然不会导致查询导致延迟。
编辑2:诊断工具的屏幕截图
为了进行比较,我改变了代码,以便查询在应用程序启动时运行。我添加了一个红色箭头,表示表单出现的位置。我之前没有注意到,但是当我的同事在启动Visual Studio后第一次运行应用程序时,它的速度提高了一秒钟。随后的所有时间都比较慢。
1)同事的计算机 - 在加载Visual Studio后首次运行
2)同事的计算机 - 所有后续运行
3)我的电脑 - 全部运行
因此,每当我的同事运行应用程序时(除了第一次),除了通常的延迟之外还有第二次暂停。启动Visual Studio后立即进行的第一次运行似乎消除了第二次暂停,但它仍然没有接近我计算机上的速度。
顺便提一下,应用程序启动会导致大约四分之一秒的正常延迟。如果我将应用程序更改为需要单击第一个查询的按钮,则仅在单击按钮后才会发生第二次暂停和通常的2秒延迟。
另一个需要注意的是应用程序使用的内存量。大部分时间在我的电脑上它将使用大约40MB,但在另一台计算机上它似乎从未使用超过35MB。是否会出现某种内存优化,这会降低其他计算机的速度?也许我的计算机正在将一些额外的/缓存的信息加载到其他人必须生成的内存中。如果这是可能的,有什么想法,我可能会寻找这个?
编辑3
我一直在推迟对模型和数据库进行更改,因为我担心延迟会回来,而且我没有任何可以测试的东西。我只想补充一点,在考虑了所有其他可能性之后,我尝试修改了POCO和数据库,它在我的计算机上仍然很快,但在其他计算机上却很慢。
我已经改变了这个问题的标题,以便更准确地反映我试图解决的问题。
答案 0 :(得分:1)
SQL Server中的查询计划可能会随时间而变化。可能是您的计算机缓存了一个好的查询计划,而您的计算机机器却没有。换句话说,它可能与EF无关。您可以通过在管理工作室中手动运行相同的查询来确认或否认此理论。
答案 1 :(得分:0)
为了解决与EF
生成的查询相关的性能问题,我建议您使用Profiler或alternative(因为Express Editions没有它)来查看多少实际上,您的时间用于运行查询。
如果大部分时间用于运行查询,正如jackmott已经建议的那样,您可以在SSMS
中通过切换Actual Execution Plan来运行查询,以查看每种情况下生成的计划。
如果花时间花在别的东西上(某些C#正在升温或类似的东西),Visual Studio 2015有builtin performance analysis可以用来查看它花费的时间。