En mi oficina, tenemos una consulta que es bastante fea, pero que funciona bastante bien en la producción y en el entorno de desarrollo (20 segundos y 4 segundos respectivamente). Sin embargo, en nuestro entorno de prueba, lleva más de 4 horas. SQL2005 (+ parches más recientes) se está ejecutando en producción y desarrollo. SQL2008R2 se está ejecutando en las pruebas.
Eché un vistazo al Plan de consulta, y muestra que SQL2008R2 está utilizando TempDB, a través de un Spool de tabla (spool perezoso) para almacenar las filas devueltas desde el servidor vinculado. El siguiente paso es mostrar Nested Loops (izquierda anti semi-unión) como consumiendo el 96.3% de la consulta. ¡La línea entre los dos operadores está en 5,398MB!
El plan de consulta para el SQL 2005 no muestra el uso de tempdb ni el uso de una Anti Semi Join Izquierda.
A continuación se muestra el código desinfectado y los planes de ejecución, el plan de 2005 en la parte superior, el 2008R2 en la parte inferior.
¿Qué está causando la drástica desaceleración y cambio? Esperaba ver un plan de ejecución diferente, así que eso no me molesta. La dramática desaceleración en el tiempo de consulta es lo que me preocupa.
¿Tengo que mirar el hardware subyacente, ya que la versión 2008R2 está usando tempdb, tengo que ver cómo optimizar el uso de eso?
¿Hay una mejor manera de escribir la consulta?
Gracias por la ayuda.
INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT
Table1.iGroupID,
GETDATE()
FROM Table1
WHERE
NOT EXISTS (
SELECT 1
FROM LinkedServer.Database.Table2 Alias2
WHERE
(
Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
AND NOT Alias2.FirstName IS NULL
AND NOT Alias2.LastName IS NULL
) OR (
Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
AND NOT Alias2.Familyname IS NULL
AND NOT Alias2.Child1Name IS NULL
) OR (
Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
AND NOT Alias2.StepFamilyName IS NULL
AND NOT Alias2.StepFamilyNameChild1 IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
)
) AND NOT EXISTS (
SELECT 1
FROM Table3
INNER JOIN Table4
ON Table4.FirstNameType = Table3.FirstNameType
INNER JOIN table5
ON table5.LastNameType = Table3.LastNameType
WHERE
Table3.iGroupID = Table1.iGroupID
AND Table3.bIsClosed = 0
AND Table4.sNameTypeConstant = 'new_lastname'
AND table5.sFirstNameConstant = 'new_firstname'
)
:: EDITAR :: Ejecuté la consulta desde una instancia SQL2005 diferente, más o menos el mismo plan de ejecución que el "bueno". Todavía no estoy seguro de cómo las dos versiones de 2005 funcionan mejor para el servidor vinculado 2008R2, que las instancias de 2008R2 a las instancias de 2008R2.
Si bien no niego que el código podría usar algo de trabajo, si el problema fuera el código, ¿no vería los mismos planes ejecutivos en todas mis pruebas? Independientemente de la versión de SQL?
:: EDITAR :: He aplicado SP1 y CU3 a las dos instancias de 2008R2, todavía no hay dados. He establecido específicamente la colocación en el servidor vinculado, sin dados. He establecido específicamente permisos de mi cuenta de usuario para ser administrador del sistema en ambas instancias, sin dados. También he recordado mis aspectos internos y la resolución de problemas de mi servidor sql 2008, veremos si puedo rastrear esto de alguna manera.
Gracias a todos por la ayuda y los consejos.
:: EDITAR :: He realizado varios cambios de permisos en el servidor vinculado. He usado inicios de sesión de SQL, inicios de sesión de dominio, he suplantado a usuarios, he usado la opción "hacerse usando este contexto de seguridad". He creado usuarios en ambos lados del servidor vinculado que tienen derechos de administrador del sistema en el servidor. Se me acabaron las ideas.
Todavía me gustaría saber por qué SQL2005 está ejecutando la consulta tan dramáticamente diferente de SQL2008R2. Si la consulta fuera mala, vería el tiempo de ejecución de más de 4 horas en SQL2005 y SQL2008R2.