请参阅下面的查询。对象和属性名称有些模糊,不会泄露机密/敏感信息,但查询结构是相同的。
添加.OrderBy(p => "")
时,这对我来说完全没有意义,查询运行得更快。执行查询所需的时间来自约。 2000毫秒到大约400毫秒。我已经测试了几次,只添加和删除了OrderBy语句。
我完全不解,这怎么可能?该查询在Azure环境中的SQL数据库上执行。
我可以理解,在属性A上排序数据,然后选择属性A等于某个值的记录可能会加速查询。但订购空字符串!?这是怎么回事?
另外我想要注意的是,没有OrderBy的查询使用表达式(如suggested in this post to circumvent SQL parameter sniffing)将执行时间也降低到约。 400毫秒。添加.OrderBy(p => "")
然后没有任何明显的区别。
var query = (from p in Context.Punders.Where(p => p.A == A)
.Where(p => null != p.SomeNumber)
.Where(p => p.StatusCode == Default ||
p.StatusCode == Cancelled)
.Where(p => p.DatePosted >= startDate && p.DatePosted <= endDate)
join f in Context.Founders.Where(f => f.A == A) on p.Code equals f.Code
join r in Context.Rounders.Where(r => r.A == A) on p.Code equals r.Code
into rg
from r in rg.DefaultIfEmpty()
join pt in Context.FishTypes.Where(ft => ft.A ==A) on p.Code equals pt.Code
where r == null
select new
{
p.Code,
f.B,
f.C,
p.D,
p.E,
pt.F,
pt.G,
p.H
})
.OrderBy(p => "");
不使用.OrderBy(...
SELECT [Filter1].[q] AS [q],
[Filter1].[c1] AS [edoc],
[Filter1].[oc1] AS [wnrdc],
[Filter1].[otc1] AS [weener],
[Filter1].[ptc1] AS [pmtpdc],
[Extent4].[isr] AS [isr],
[Extent4].[rac] AS [rac],
[Filter1].[arn] AS [arn]
FROM (SELECT [Extent1].[pcid] AS [pcid1],
[Extent1].[edoc] AS [c1],
[Extent1].[pmtpdc] AS [ptc1],
[Extent1].[q] AS [q],
[Extent1].[arn] AS [arn],
[Extent1].[dateposted] AS [DatePosted],
[Extent2].[pcid] AS [pcid2],
[Extent2].[wnrdc] AS [oc1],
[Extent2].[weener] AS [otc1]
FROM [fnish].[post] AS [Extent1]
INNER JOIN [fnish].[olik] AS [Extent2]
ON [Extent1].[olikedoc] = [Extent2].[edoc]
LEFT OUTER JOIN [fnish].[receivable] AS [Extent3]
ON ( [Extent3].[pcid] = @p__linq__4 )
AND ( [Extent1].[edoc] =
[Extent3].[pepstedoc] )
WHERE ( [Extent1].[arn] IS NOT NULL )
AND ( [Extent1].[posttedoc] IN ( N'D', N'X' ) )
AND ( [Extent3].[id] IS NULL )) AS [Filter1]
INNER JOIN [fnish].[paymenttype] AS [Extent4]
ON [Filter1].[ptc1] = [Extent4].[edoc]
WHERE ( [Filter1].[pcid1] = @p__linq__0 )
AND ( [Filter1].[dateposted] >= @p__linq__1 )
AND ( [Filter1].[dateposted] <= @p__linq__2 )
AND ( [Filter1].[pcid2] = @p__linq__3 )
AND ( [Extent4].[pcid] = @p__linq__5 )
使用.OrderBy(...
SELECT [Project1].[q] AS [q],
[Project1].[edoc] AS [edoc],
[Project1].[wnrdc] AS [wnrdc],
[Project1].[weener] AS [weener],
[Project1].[pmtpdc] AS [pmtpdc],
[Project1].[isr] AS [isr],
[Project1].[rac] AS [rac],
[Project1].[arn] AS [arn]
FROM (SELECT N'' AS [C1],
[Filter1].[c1] AS [edoc],
[Filter1].[ptc1] AS [pmtpdc],
[Filter1].[q] AS [q],
[Filter1].[arn] AS [arn],
[Filter1].[oc1] AS [wnrdc],
[Filter1].[otc1] AS [weener],
[Extent4].[isr] AS [isr],
[Extent4].[rac] AS [rac]
FROM (SELECT [Extent1].[pcid] AS [pcid1],
[Extent1].[edoc] AS [c1],
[Extent1].[pmtpdc] AS [ptc1],
[Extent1].[q] AS [q],
[Extent1].[arn] AS [arn],
[Extent1].[dateposted] AS [DatePosted],
[Extent2].[pcid] AS [pcid2],
[Extent2].[wnrdc] AS [oc1],
[Extent2].[weener] AS [otc1]
FROM [fnish].[post] AS [Extent1]
INNER JOIN [fnish].[olik] AS [Extent2]
ON [Extent1].[olikedoc] = [Extent2].[edoc]
LEFT OUTER JOIN [fnish].[receivable] AS [Extent3]
ON ( [Extent3].[pcid] =
@p__linq__4 )
AND ( [Extent1].[edoc] =
[Extent3].[pepstedoc] )
WHERE ( [Extent1].[arn] IS NOT NULL )
AND ( [Extent1].[posttedoc] IN ( N'D', N'X' ) )
AND ( [Extent3].[id] IS NULL )) AS [Filter1]
INNER JOIN [fnish].[paymenttype] AS [Extent4]
ON [Filter1].[ptc1] = [Extent4].[edoc]
WHERE ( [Filter1].[pcid1] = @p__linq__0 )
AND ( [Filter1].[dateposted] >= @p__linq__1 )
AND ( [Filter1].[dateposted] <= @p__linq__2 )
AND ( [Filter1].[pcid2] = @p__linq__3 )
AND ( [Extent4].[pcid] = @p__linq__5 )) AS [Project1]
ORDER BY [Project1].[c1] ASC
从我所学到的,有点猜测:这是特定于案例的行为。就我而言,性能提升可能是由于SQL服务器构造的不同执行计划产生了性能更好的查询。我已经看到了一个不同的执行计划,其中OrderBy
没有使用显示类似性能增益的SQL语句OPTION(RECOMIPILE)
的{{1}}。因此,很可能(我认为)将OrderBy
添加到LINQ查询中会产生一个不同的执行计划,从而产生性能更好的查询。
答案 0 :(得分:2)
给出你的笔记
另外我想注意,那个查询,没有OrderBy,使用 表达式(如本文所述,用于规避SQL参数 嗅探)将执行时间也降低到约。 400毫秒。添加 .OrderBy(p =&gt;&#34;&#34;)然后没有任何明显的区别。
最合理的解释是:OrderBy
与使用显式值而不是参数具有相同的效果。因此,如果您有针对给定查询的预缓存计划,并且使用特定参数值,则此计划不是最佳的(2秒) - 通过向其添加无用OrderBy
来更改此查询将强制SQL Server为其创建新的执行计划这个查询,否则将否定旧的非最佳执行计划的影响。当然,应该清楚的是,这不是否定计划缓存的好方法。