Sql server 链接服务器查询中的参数从varchar转换为nvarchar,导致索引扫描和性能下降

Sql server 链接服务器查询中的参数从varchar转换为nvarchar,导致索引扫描和性能下降,sql-server,linked-server,nvarchar,Sql Server,Linked Server,Nvarchar,我们有以下设置: 源服务器版本12或15,校对Latin1_General_CI_AS(在我们的责任范围内,我们可以在此处更改所有内容) 链接服务器版本13,排序规则:Latin1_General_CI_AS(不在我们的责任范围内,我们不能在此处更改任何内容) 链接数据库排序:SQL\uLatin1\u General\u CP1\u CI\u AS NHibernate被用作ORM来创建查询(这意味着:灵活性较低),而链接服务器上的表只需要很少的查询 链接服务器选项: sp_addlinke

我们有以下设置:

  • 源服务器版本12或15,校对Latin1_General_CI_AS(在我们的责任范围内,我们可以在此处更改所有内容)
  • 链接服务器版本13,排序规则:Latin1_General_CI_AS(不在我们的责任范围内,我们不能在此处更改任何内容)
  • 链接数据库排序:SQL\uLatin1\u General\u CP1\u CI\u AS
  • NHibernate被用作ORM来创建查询(这意味着:灵活性较低),而链接服务器上的表只需要很少的查询
  • 链接服务器选项: sp_addlinkedserver@server=N'MyLinkedServer',@srvpproduct=N'SQL server'

    'collation compatible='false', '数据访问='true', 'dist='false', “pub='false', “rpc='false', “rpc out='false', “sub='false', '连接超时='0', '排序规则名称=ull, “惰性模式验证='false', “查询超时='0', “使用远程排序规则='true', '远程进程事务升级='true'

目标表TargetTableOnLinkedServer列如下所示:

PrimaryKey varchar(23)
OtherThing varchar(42)
SELECT OtherThing FROM TargetTableOnLinkedServer WHERE PrimaryKey = 'Hello World'
EXEC sp_executesql N'SELECT MyColumn FROM MyLinkedServer.MyDatabase.dbo.MyTable A WHERE A.MyColumn = @p1',N'@p1 varchar(8000)', @p1='MyValue'
我们发出如下查询:

PrimaryKey varchar(23)
OtherThing varchar(42)
SELECT OtherThing FROM TargetTableOnLinkedServer WHERE PrimaryKey = 'Hello World'
EXEC sp_executesql N'SELECT MyColumn FROM MyLinkedServer.MyDatabase.dbo.MyTable A WHERE A.MyColumn = @p1',N'@p1 varchar(8000)', @p1='MyValue'
我们还尝试使用
sp_execute
,参数为varchar(8000)-下面是更详细的查询

在SQL server profiler中,我们看到链接查询基本上被转换为:

SELECT OtherThing FROM TargetTableOnLinkedServer WHERE PrimaryKey = N'Hello World'
请注意这里的“N”。“N”(在Nvarchar中)导致索引扫描,而不是索引查找。 不幸的是,我们无法找到一种方法来抑制N,也不知道原因

是否有办法防止“链接服务器机制”将参数“转换”为unicode字符串(通过添加N)

提前谢谢


有关查询的更多详细信息:

SELECT MyColumn FROM MyLinkedServer.MyDatabase.dbo.MyTable A WHERE A.MyColumn = 'MyValue'
这将导致链接服务器上发生探查器SP:StmtCompleted事件

和RPC:Completed事件:

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,NULL,N'SELECT "Tbl1001"."MyColumn" "Col1003" FROM "MyDatabase"."dbo"."MyTable" "Tbl1001" WHERE "Tbl1001"."MyColumn"=N''MyValue'''
select @p1
NHibernate创建如下查询:

PrimaryKey varchar(23)
OtherThing varchar(42)
SELECT OtherThing FROM TargetTableOnLinkedServer WHERE PrimaryKey = 'Hello World'
EXEC sp_executesql N'SELECT MyColumn FROM MyLinkedServer.MyDatabase.dbo.MyTable A WHERE A.MyColumn = @p1',N'@p1 varchar(8000)', @p1='MyValue'
请注意varchar和缺少“N”。 这将导致以下带有索引扫描的查询(至少这显示了在SMSS中复制粘贴查询时的执行计划):

使用索引搜索时,正确的结果如下所示:

exec sp_prepexec @p1 output,N'@P1 varchar(4000)',N'SELECT "Tbl1001"."MyColumn" "Col1004" FROM "MyDatabase"."dbo"."MyTable" "Tbl1001" WHERE "Tbl1001"."MyColumn"=@P1','MyValue'
select @p1
我还尝试使用另一个提供程序MSOLEDBSQL(显然是最现代的一个),没有任何更改:

EXEC master.dbo.sp_addlinkedserver @server = N'MyServer', @srvproduct=N'', @provider=N'MSOLEDBSQL', @provstr=N'Server=MyServerName'

您是如何运行查询的?SQL不会将文本字符串转换为
nvarchar
,因此您将传递一个文本字符串,从而进行扫描<代码>EXEC sp_executesql N'从TargetTableOnLinkedServer中选择其他内容,其中PrimaryKey=''Hello World''不会将
varchar
'Hello World'
)转换为
nvarchar
N'Hello World'
);这意味着你所做的一切都是原因(你没有告诉我们)。@larnu谢谢你的回答。这是我的假设。您能检查一下更详细的、真实的实时查询吗?您的问题似乎有点类似于,但这是来自JDBC。链接服务器的定义是什么?它使用什么提供商?@Martin Smith谢谢。我已经添加了上面链接服务器的选项。上面的示例是我在链接服务器上运行探查器时,通过在SMSS中进行手动查询创建的。链接服务器的选项是100%标准的。我无法想象这里会有什么不端行为。