【发布时间】:2015-10-12 11:59:00
【问题描述】:
以下查询(没有详细信息)以超时结束。所有列都有 nvarchar 类型。所以这与this 无关。查询在没有 sp_executesql 的情况下也能完美运行。
exec sp_executesql N'declare @exp nvarchar(max) = ''%'' + @name + ''%''
select u.Id
from [local_db]..Users u
join [linked_server].[remote_db].dbo.Players p on p.PlayerId = u.PlayerId
join [linked_server].[remote_db].dbo.PlayerStats ps on ps.PlayerId = u.PlayerId
where @exp is null or u.Nickname like @exp or u.Name like @exp or p.Nickname like @exp
order by ps.Wins desc
offset @skip rows fetch next @take rows only',N'@skip int,@take int,@name nvarchar(8)',@skip=0,@take=24,@name=N'Foo'
我发现了一些有趣的细节。如果我删除or p.Nickname like @exp,它会起作用。当我删除or u.Nickname like @exp or u.Name like @exp 时,也会发生同样的情况。但这只是一个想法。
更新
下一个查询工作正常!
exec sp_executesql N'
declare @skip int = 0, @take int = 24, @name nvarchar(8) = N''Foo''
declare @exp nvarchar(max) = ''%'' + @name + ''%''
select u.Id
from [local_db]..Users u
join [linked_server].[remote_db].dbo.Players p on p.PlayerId = u.PlayerId
join [linked_server].[remote_db].dbo.PlayerStats ps on ps.PlayerId = u.PlayerId
where @exp is null or u.Nickname like @exp or u.Name like @exp or p.Nickname like @exp
order by ps.Wins desc
offset @skip rows fetch next @take rows only'
【问题讨论】:
-
性能问题是因为您通过使用前导通配符将整个查询呈现为 nonSARGable。当您搜索较少的列时它“工作”的原因是因为它能够足够快地扫描其他列以避免超时。
-
但没有 sp_executesql 也能完美运行。
-
我不确定我会说得很完美,因为它无疑很慢。从您发布的内容来看,我看不出有任何理由使用动态 sql。此查询是否还有更多需要您使用动态 sql 的内容?
-
这个查询是由实体框架创建的,当调用Database.SqlQuery方法时。
-
呃,我从未使用过 EF,但从我所看到的一切来看,它创建了一些最糟糕的 sql。有没有办法让它不使用前导通配符,或者这是搜索正常工作的要求?遗憾的是,您几乎无法做任何事情来加快速度,因为这些列上的任何索引都无法使用。
标签: sql-server entity-framework timeout sp-executesql