En pocas palabras : al agregar criterios a la WHEREcláusula y dividir la consulta en cuatro consultas separadas, una para cada campo permitió que el servidor SQL proporcionara un plan paralelo e hizo que la consulta se ejecutara 4 veces más rápido que antes sin la prueba adicional en la WHEREcláusula. Dividir las consultas en cuatro sin la prueba no hizo eso. Tampoco agregar la prueba sin dividir las consultas. La optimización de la prueba redujo el tiempo total de ejecución a 3 minutos (desde las 3 horas originales).
Mi UDF original tardó 3 horas y 16 minutos en procesar 1.174.731 filas, con 1.216 GB de datos de nvarchar probados. Utilizando el CLR proporcionado por Martin Smith en su respuesta, el plan de ejecución aún no era paralelo y la tarea tomó 3 horas y 5 minutos.

Después de leer ese WHEREcriterio podría ayudar a empujar a un UPDATEparalelo, hice lo siguiente. Agregué una función al módulo CLR para ver si el campo tenía una coincidencia con la expresión regular:
[SqlFunction(IsDeterministic = true,
IsPrecise = true,
DataAccess = DataAccessKind.None,
SystemDataAccess = SystemDataAccessKind.None)]
public static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
{
string s = replacementSpec.Value;
ReplaceSpecification rs;
if (!cachedSpecs.TryGetValue(s, out rs))
{
var doc = new XmlDocument();
doc.LoadXml(s);
rs = new ReplaceSpecification(doc);
cachedSpecs[s] = rs;
}
return rs.IsMatch(inputString.ToString());
}
y, en internal class ReplaceSpecification, agregué el código para ejecutar la prueba contra la expresión regular
internal bool IsMatch(string inputString)
{
if (Regex == null)
return false;
return Regex.IsMatch(inputString);
}
Si todos los campos se prueban en una sola declaración, el servidor SQL no paraleliza el trabajo
UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X),
DE461 = dbo.ReplaceMultiWord(DE461, @X),
DE87 = dbo.ReplaceMultiWord(DE87, @X),
DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
AND (dbo.CanReplaceMultiWord(IndexedXml, @X) = 1
OR DE15 = dbo.ReplaceMultiWord(DE15, @X)
OR dbo.CanReplaceMultiWord(DE87, @X) = 1
OR dbo.CanReplaceMultiWord(DE15, @X) = 1);
Tiempo para ejecutar más de 4 1/2 horas y aún en ejecución. Plan de ejecución:

Sin embargo, si los campos se separan en declaraciones separadas, se usa un plan de trabajo paralelo y mi uso de CPU pasa del 12% con los planes en serie al 100% con los planes paralelos (8 núcleos).
UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(IndexedXml, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE461 = dbo.ReplaceMultiWord(DE461, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE461, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE87 = dbo.ReplaceMultiWord(DE87, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE87, @X) = 1;
UPDATE dbo.DeidentifiedTest
SET DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
AND dbo.CanReplaceMultiWord(DE15, @X) = 1;
Tiempo para ejecutar 46 minutos. Las estadísticas de fila mostraron que aproximadamente el 0.5% de los registros tenían al menos una coincidencia de expresiones regulares. Plan de ejecución:

Ahora, el lastre principal en el tiempo era la WHEREcláusula. Luego reemplacé la prueba de expresiones regulares en la WHEREcláusula con el algoritmo Aho-Corasick implementado como un CLR. Esto redujo el tiempo total a 3 minutos y 6 segundos.
Esto requirió los siguientes cambios. Cargue el ensamblaje y las funciones para el algoritmo Aho-Corasick. Cambiar la WHEREcláusula a
WHERE InProcess = 1 AND dbo.ContainsWordsByObject(ISNULL(FieldBeingTestedGoesHere,'x'), @ac) = 1;
Y agregue lo siguiente antes del primero UPDATE
DECLARE @ac NVARCHAR(32);
SET @ac = dbo.CreateAhoCorasick(
(SELECT NAMES FROM dbo.NamesMultiWord FOR XML RAW, root('root')),
'en-us:i'
);
SELECT @var = REPLACE ... ORDER BYse garantiza que la construcción funcione como espera. Ejemplo de elemento de conexión (consulte la respuesta de Microsoft). Por lo tanto, cambiar a SQLCLR tiene la ventaja adicional de garantizar resultados correctos, lo que siempre es bueno.