EF6 查询预编译

Posted

技术标签:

【中文标题】EF6 查询预编译【英文标题】:EF6 Query Precompilation 【发布时间】:2015-07-03 03:33:35 【问题描述】:

有没有办法对 EF 查询进行预编译,让应用无需编译(即使是第一次执行)?

我有很多复杂的查询,在使用 L2E 时需要一些时间来执行。例如,对于我对 Sql Server profiler 进行基准测试的一个查询报告大约 300 毫秒的执行时间,但实际上这个查询在我的 PC 上大约 4.5 秒后完成(至强四核 2.6 GHz 和 8 GB 的 RAM。这意味着我的 PC 正在等待数据到达大约 0.5 秒,并且花费大约 4 秒来编译和执行查询,最后读取我的 PC 上的数据(只有 4 条记录)。那是很多时间,特别是因为 ToListAsyncs() 不会将控制权返回给UI 直到实际查询被发送到数据库,这意味着我的应用程序在所有 4 秒内都“挂起”。解决此问题的一种方法是使用 Task.Run() 而不是 ToListAsync,但这只会让我的应用程序显示一些等待签到,还是会有4s的延迟。

在一些较旧的 PC 上,这可能意味着用户将等待 10 秒进行查询编译,这不是我们所希望的。那么,任何人都知道如何预编译所有查询,以便即使是第一次执行它们也不会延迟?

【问题讨论】:

实体框架 2011 年 6 月 CTP 支持称为自动编译的 LINQ 查询的新功能。现在,您自动执行的每个 LINQ to Entities 查询都会被编译并放置在 EF 的查询缓存中。每次运行查询时,EF 都会在其查询缓存中找到它,而不必再次执行整个编译过程。 blogs.msdn.com/b/efdesign/archive/2011/06/30/…如果你禁用了查询缓存,它将无法工作 @Legends 这不是一个真正的解决方案,原因有两个:1)在桌面应用程序中,某些查询一天只能执行一次 - 这意味着查询实际上永远不会被编译,2)大多数我的查询在 where 查询中包含 Enumerable.Contains。这在执行 SP 时可以正常工作,您可以在其中使用 TVP(在 EF 中支持),但是当使用 L2E 时,每次执行查询时都会生成一个新查询,因此没有自动查询编译。跨度> 我不是 EF Geek,但作为一种解决方法,我建议您在应用程序启动时异步预编译所有查询,例如,您有 30 个查询,但以这种方式排序,即最常用的首先编译,而不太常用的则在编译执行管道中稍后编译。客户端或服务器上的数据库在哪里?如果是服务器端,放弃LTE,使用纯T-SQL,这样执行计划就会缓存在db中。如果数据库在客户端,也许这也可以工作,但无法确认。 关键是在 L2E 查询中使用 Enumerable.Contains(...) 时无法编译它们,这是我在阅读该主题时才发现的。正如我在之前的评论中所说,TVP 可以在 EF6 中与 SP 一起正常工作,但为了可维护性,客户决定不使用 SP。 我有同样的问题:使用 EF6,我多次调用的查询没有预编译,需要很长时间才能完成。查询又长又复杂,我每次调用它时只调用它发送不同的输入参数(字符串)。我已经尝试了所有方法,但仍然无法正常工作(我没有调用 Enumerable.Contains(...) 这是唯一的限制。知道为什么吗?如此绝望,感谢任何帮助。 【参考方案1】:

我相信您正在寻找的概念是“预生成的映射视图” — https://msdn.microsoft.com/en-us/data/dn469601.aspx

在搜索该功能时,我还看到了这篇相当近期的相关文章 — http://www.fusonic.net/en/blog/2014/07/09/three-steps-for-fast-entityframework-6.1-first-query-performance/

请注意,在 EF 5 中添加了自动编译 LINE-to-Entities 查询的支持,因此不再每次都进行编译 — https://msdn.microsoft.com/en-us/data/hh949853.aspx#4

【讨论】:

不,这不是我要说的,视图将在第一次执行查询时生成,通常是在应用程序启动时。我说的是预编译一个复杂的查询,这样 EF6 就不需要在每次执行 L2E 查询时都生成一个。根据我到目前为止所读到的内容,如果您有复杂的 L2E 查询,例如: where Enumerable.Contains(x.Id),使用当前版本的 EF6 是不可能实现这一点的,您将最每次执行查询时都会受到编译性能的影响, 我已更新我的答案以包含编译 LINQ-to-Entities 查询的单独主题。 您是正确的,使用 IEnumerable<T>.Contains<T>(T value) 的查询无法被缓存。虽然上一篇文章指出 EF 6 中的查询性能有所提高。 我已经知道 EF6 中的自动编译功能,并且我已经在问题 cmets 中与 @Legend 讨论过。这对我所描述的问题没有帮助。 我觉得我的回答是有效的。预生成映射视图将导致在第一次执行查询时跳过该步骤。从您的问题来看,这似乎是您正在寻找的。​​span>

以上是关于EF6 查询预编译的主要内容,如果未能解决你的问题,请参考以下文章

PDO预编译语句执行查询与DML操作

PHP7预编译mysqli查询操作

关于jdbc预编译下模糊查询的写法

关于mysql使用prepare关键字预编译语句后是否使用deallocate的区别

什么是预编译 SQL 语句? [复制]

JAVA带预编译的模糊查询问题