In the plans you posted we can see it's transferring more records (more network I/O), and it's also converting both the arguments you deliver to it, as well as converting the output upon inserting.
By the looks of it the remote DB has it's field as a N(VAR)CHAR instead of (VAR)CHAR. So when you're quering it using VARCHAR expression, it first has to convert these and also COLLATE them to the right character set.
2 of the 3 tables/sources hit are running somewhat fine. But one takes up nearly all the time:
<RunTimeCountersPerThread Thread="0" ActualRebinds="4787" ActualRewinds="0"
ActualRows="2228" Batches="0" ActualEndOfScans="2559" ActualExecutions="4787"
ActualExecutionMode="Row" ActualElapsedms="49195" ActualCPUms="48521" ActualScans="0"
ActualLogicalReads="0" ActualPhysicalReads="0" ActualReadAheads="0"
ActualLobLogicalReads="0" ActualLobPhysicalReads="0" ActualLobReadAheads="0"/>
</RunTimeInformation>
<RemoteQuery RemoteSource="NET2-1\NET2" RemoteQuery="SELECT "Expr1018" FROM
(SELECT "Col1036",MAX("Col1031") "Expr1018" FROM (SELECT
"Tbl1017"."Address" "Col1024", "Tbl1017"."SubAddr" "Col1025", "Tbl1017"."Name""Col1026",
"Tbl1017"."PeripheralID" "Col1023","Tbl1017"."Type" "Col1027" FROM "net2"."dbo"."Peripherals" "Tbl1017"
WHERE "Tbl1017"."Name" like N'%(In)%' COLLATE Latin1_General_CI_AS
AND (NOT "Tbl1017"."Name" like N'%(Internal)%' COLLATE Latin1_General_CI_AS
AND NOT "Tbl1017"."Name" like N'%Cats%' COLLATE Latin1_General_CI_AS
AND NOT "Tbl1017"."Name" like N'%Dingle%' COLLATE Latin1_General_CI_AS OR "Tbl1017"."Name" like N'%(Internal)%' COLLATE Latin1_General_CI_AS
AND ("Tbl1017"."Name" like N'%Cats%' COLLATE Latin1_General_CI_AS OR "Tbl1017"."Name" like N'%Dingle%' COLLATE Latin1_General_CI_AS))) Qry1028,
(SELECT "Tbl1015"."EventTime" "Col1031", "Tbl1015"."EventType" "Col1032", "Tbl1015"."Address" "Col1034", "Tbl1015"."SubAddr" "Col1035","Tbl1015"."UserID" "Col1036","Tbl1015"."CardNo" "Col1037",
"Tbl1015"."EventSubType" "Col1033","Tbl1015"."EventID" "Col1030"
FROM "Net2Events"."dbo"."Events" "Tbl1015" WHERE "Tbl1015"."EventType"=(20)
AND "Tbl1015"."EventTime"<?) Qry1038 WHERE "Col1024"="Col1034" AND "Col1025"="Col1035" GROUP BY "Col1036")
Qry1039 WHERE "Col1036"=?"/>
In the above query you can see a ton of like compares with collation. I suspect this is the slowdown. We can see it has a ~50 seconds execution time of which the most is CPU (which would suggest it's converting and comparing).
I would try to see if making both your temporary table use NVARCHARS as well as specifying your where arguments as N'' helps out. If not you can always try and use Openrowset and force execution entirely on remote side.
Basically in this case, you have two slow down factors. The 3 seperate executions (more data being transferred), as well as this last query from the execution plan which takes 50 seconds to execute on its own.
My apologies for the XML formatting, i already made it a lot less horrible than it is in the execution plan source.
Openrowset documentation
SELECT
only andINSERT...SELECT
is most likely the transaction binding the two systems together in the latter case. You can try changing the linked server property ofremote proc transaction promotion
/ "Enable Promotion of Distributed Transaction for RPC" to false (unless it's already false). you can also try putting that select into a stored proc on the remote system and doing anINSERT...EXEC
. Either way, cross-system DML is very prone to these issues.