【发布时间】:2013-04-12 11:48:52
【问题描述】:
我有一个包含 100 亿行的表。当我使用 where clausule 查询并且值是硬编码的(tabulka = tabulka.Where(x => x.Value.Contains("value") sql 查询作为批处理发送到 sql。大约需要 5 秒。当值没有硬编码时(tabulka = tabulka.Where(x => x.Value.Contains(value)),查询发送一个 RPC 和耗时 15 秒。
这是 EF 发送给 SQL 的真实示例(来自 Profiler):
exec sp_executesql N'SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Tabulka] AS [Extent1]
WHERE ([Extent1].[Column] LIKE @p__linq__0 ESCAPE N''~'') AND ([Extent1].[Column] LIKE @p__linq__1 ESCAPE N''~'')
) AS [GroupBy1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'%text1%',@p__linq__1=N'%text2%'
这需要 15 秒。
当我添加 OPTION (RECOMPILE) 需要 5 秒:
exec sp_executesql N'SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Tabulka] AS [Extent1]
WHERE ([Extent1].[Column] LIKE @p__linq__0 ESCAPE N''~'') AND ([Extent1].[Column] LIKE @p__linq__1 ESCAPE N''~'')
) AS [GroupBy1] OPTION (RECOMPILE)',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'%text1%',@p__linq__1=N'%text2%'
改写成简单查询也需要5秒:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Tabulka] AS [Extent1]
WHERE ([Extent1].[Column] LIKE '%text1%' AND [Extent1].[Column] LIKE '%text2%')
) AS [GroupBy1]
问题是如何强制 EF 将其作为 Batch 发送或执行某些操作以花费 5 秒而不是 15 秒。
这些查询仅作为演示,真正的查询可能要复杂得多,我不知道要重建它而不使用 IQueryable。
我们将不胜感激。 Here are execution plans for queries
【问题讨论】: