У нас есть следующие настройки:
- Исходный сервер версии 12 или 15, параметры сортировки Latin1_General_CI_AS (мы можем здесь изменить все)
- Версия 13 связанного сервера, параметры сортировки: Latin1_General_CI_AS (здесь мы не можем ничего изменить : меньше гибкости), с несколькими таблицами на связанном сервере.
Параметры связанного сервера: sp_addlinkedserver @server = N'MyLinkedServer ', @ srvproduct = N' SQL Server '
'сопоставление совместимо =' false ',' доступ к данным = 'true', 'dist =' false ',' pub = 'false', 'rpc =' false ',' rp c out = 'false ',' sub = 'false', 'connect timeout =' 0 ',' collation name = ull, 'проверка ленивой схемы =' false ',' query timeout = '0', 'use remote collation =' true ',' Remote Pro c продвижение транзакции = 'true'
Таблица назначения * 1 021 * TargetTableOnLinkedServer столбцы выглядят так:
PrimaryKey varchar(23)
OtherThing varchar(42)
Мы выдаем запрос следующим образом:
SELECT OtherThing FROM TargetTableOnLinkedServer WHERE PrimaryKey = 'Hello World'
Мы также пытаемся использовать sp_execute
с параметром varchar (8000) ) - более подробные запросы приведены ниже.
В профилировщике сервера SQL мы видим, что связанный запрос переводится в основном:
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 на связанный сервер
SELECT "Tbl1001"."MyColumn" "Col1003" FROM "MyDatabase"."dbo"."MyTable" "Tbl1001" WHERE "Tbl1001"."MyColumn"=N'MyValue'
И RP C: Завершенное событие:
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 создает такие запросы:
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):
declare @p1 int
exec sp_prepexec @p1 output,N'@P1 nvarchar(4000)',N'SELECT "Tbl1001"."MyColumn" "Col1004" FROM "MyDatabase"."dbo"."MyTable" "Tbl1001" WHERE "Tbl1001"."MyColumn"=@P1',N'MyValue'
select @p1
Правильно будет следующее при поиске по индексу:
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
Я также пытался использовать другой поставщик MSOLEDB SQL (очевидно, самый современный), без изменений:
EXEC master.dbo.sp_addlinkedserver @server = N'MyServer', @srvproduct=N'', @provider=N'MSOLEDBSQL', @provstr=N'Server=MyServerName'