A general comment is that this query is need of a major overhaul. There are all sorts of things in this query that can act as go-slower button. Unfortunately, I think the work for that rewrite goes beyond what you can expect from a forum. One tip, though, is to insert the result from these string-splitting operations into a temp table.
However, sometimes you may be lucky, and that seems to be the case on the subscriber. To wit, I found a configuration difference. In the slow plan, the optimizer has CardinalityEstimationModelVersion="140"
, whereas the fast plan has CardinalityEstimationModelVersion="70"
. Microsoft rewrote the cardinality estimator in SQL 2014 and has refined it since. Often to the better, but as often with optimization, it can sometimes backfire. Not the least with a query that was not good from the start, but where you were lucky, so you need saw any need for tuning.
To test this hypothesis, add this hint to the end of the query on the slow server:
OPTION (USE HINT('QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_110'))
The cardinality estimator can also be controlled by a database-scoped configuration or the compatibility level. I would guess that the subscriber has compatibility level < 120.