我在使用复杂EF6查询的Azure上遇到SQL性能问题。环境配置为弹性池。在开发区域中,eDTU限制经常通过CPU使用率命中,我将其归因于查询计划生成。
应用程序相当通用,因此EF查询非常复杂,但在查询的内容中,通常有一个子查询通常具有IN子句。
SELECT Id FROM Event E WHERE E.Name IN (@p__linq__1, @p__linq__2, @p__linq__3)
OR
SELECT Id FROM Event E WHERE E.Name IN (@p__linq__4, @p__linq__5)
虽然查询的其余部分是相同的,但是会生成一个新的SQL查询计划,因为文本因参数的数量而不同。
以前,在另一个项目中,我通过在连接中使用TVP而不是where子句来增加计划重用。
SELECT Id FROM Event E INNER JOIN @p_tvp_strings T ON E.Name = T.[Value]
我无法通过IQueryable方式弄清楚如何在EF中这样做。
我已经尝试创建一个Datatable并将其解析为参数但context.Database.SqlQuery不返回IQueryable。它立即执行命令。
var nameArray = new string[]
{
"Bob", "Fred", "Bill",
};
var nameTable = CreateDataTable(nameArray);
var parameter = new SqlParameter("tvp", nameTable);
parameter.SqlDbType = SqlDbType.Structured;
parameter.TypeName = "StringSet";
var names = context.Database.SqlQuery<string>("SELECT [Value] FROM @tvp", parameter).AsQueryable();
var people = context.People.Where(p => names.Contains(p.Name)).ToList();
不幸的是,这会导致生成两个查询。
declare @p3 dbo.StringSet
insert into @p3 values(N'Bob')
insert into @p3 values(N'Fred')
insert into @p3 values(N'Bill')
exec sp_executesql N'SELECT [Value] FROM @tvp',N'@tvp [StringSet] READONLY',@tvp=@p3
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent1].[Title] AS [Title],
[Extent1].[Age] AS [Age]
FROM
[dbo].[People] AS [Extent1]
WHERE
[Extent1].[Name] IN (N'Bill', N'Bob', N'Fred')
有人在使用EF时知道如何在WHERE子句中使用TVP吗?