SQL 服务器中的 EF 核心参数嗅探
EF Core Parameter Sniffing in SQL Server
我一直在观看 Brent Ozar 的培训视频(对我来说是 SQL 大师),他谈到了参数嗅探并说 EF 可以做到这一点,但对于我来说,我无法找到一个有效的例子。我期待看到参数,但它只是创建了这样的 SQL,只是相等,而不是 @p1、@p2。
SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = 6) AND ([p].[CreationDate] >= '2011-01-01T00:00:00.000')
我通过搭建他的 Whosebug2013 数据库创建了 DBContext,并在 post 类型上创建了一个外键以获得某种 JOIN。
有谁知道我如何获得使用 EF 进行参数嗅探的示例,因为这每次都会创建一个新的查询计划?
如果我调用存储过程,那么我可以获得参数嗅探。
我的C#代码如下
var result = ctx.Posts
.Include(x => x.PostType)
.Where(x => x.PostTypeId == 6 && x.CreationDate >= new DateTime(2013, 01, 01))
.Select(x => new {
Id = x.Id,
Body = x.Body,
Type = x.PostType.Type
}).ToList();
很快我就找到了答案:)
正如 Gert 在评论中所说,我必须传递一个变量,因此 EF 在那里发挥了一些作用。
因此,如果我将代码更改为此,则会发生:
var myId = 6;
var result = ctx.Posts
.Include(x => x.PostType)
.Where(x => x.PostTypeId == myId && x.CreationDate >= new DateTime(2013, 01, 01))
.Select(x => new {
Id = x.Id,
Body = x.Body,
Type = x.PostType.Type
}).ToList();
然后我得到 SQL 这样的
exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=6
然后我可以用不同的值执行另一个
exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=7
然后我可以在执行计划中看到使用了相同的查询计划,因为顶部的第一个查询设置了计划,然后第二个使用它并保留了估计的 166 行但实际上只有 4向后排
如果我查看第二个查询属性,我也可以确认这一点,并且可以看到它是用 6 编译的 put was 运行 with 7
我一直在观看 Brent Ozar 的培训视频(对我来说是 SQL 大师),他谈到了参数嗅探并说 EF 可以做到这一点,但对于我来说,我无法找到一个有效的例子。我期待看到参数,但它只是创建了这样的 SQL,只是相等,而不是 @p1、@p2。
SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = 6) AND ([p].[CreationDate] >= '2011-01-01T00:00:00.000')
我通过搭建他的 Whosebug2013 数据库创建了 DBContext,并在 post 类型上创建了一个外键以获得某种 JOIN。
有谁知道我如何获得使用 EF 进行参数嗅探的示例,因为这每次都会创建一个新的查询计划?
如果我调用存储过程,那么我可以获得参数嗅探。
我的C#代码如下
var result = ctx.Posts
.Include(x => x.PostType)
.Where(x => x.PostTypeId == 6 && x.CreationDate >= new DateTime(2013, 01, 01))
.Select(x => new {
Id = x.Id,
Body = x.Body,
Type = x.PostType.Type
}).ToList();
很快我就找到了答案:)
正如 Gert 在评论中所说,我必须传递一个变量,因此 EF 在那里发挥了一些作用。 因此,如果我将代码更改为此,则会发生:
var myId = 6;
var result = ctx.Posts
.Include(x => x.PostType)
.Where(x => x.PostTypeId == myId && x.CreationDate >= new DateTime(2013, 01, 01))
.Select(x => new {
Id = x.Id,
Body = x.Body,
Type = x.PostType.Type
}).ToList();
然后我得到 SQL 这样的
exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=6
然后我可以用不同的值执行另一个
exec sp_executesql N'SELECT [p].[Id], [p].[Body], [p0].[Type]
FROM [Posts] AS [p]
INNER JOIN [PostTypes] AS [p0] ON [p].[PostTypeId] = [p0].[Id]
WHERE ([p].[PostTypeId] = @__myId_0) AND ([p].[CreationDate] >= ''2013-01-01T00:00:00.000'')',N'@__myId_0 int',@__myId_0=7
然后我可以在执行计划中看到使用了相同的查询计划,因为顶部的第一个查询设置了计划,然后第二个使用它并保留了估计的 166 行但实际上只有 4向后排
如果我查看第二个查询属性,我也可以确认这一点,并且可以看到它是用 6 编译的 put was 运行 with 7