SELECT TOP 1 perjudica el rendimiento de la consulta; ¿Hay alguna manera accesible de dba para superar esto?

13

En una aplicación de producción (C # hablando con SQL Server 2014 Standard) hay una consulta que se ve así, a continuación. La mayoría de las veces se ejecuta en milisegundos. Pero ocasionalmente (para ciertos valores de @Id), se vuelve loco y toma un minuto más o menos. Esto es más largo que el tiempo de espera de la aplicación, por lo que la aplicación falla para el usuario.

En los casos "se vuelve loco", el conjunto de resultados devuelto está vacío correctamente, como en muchos casos, pero no en todos los demás.

Afortunadamente, esto es reproducible tanto en los entornos de producción como de desarrollo.

El desarrollador dice que eliminar "TOP 1" de la consulta, luego asegurarse de que la aplicación consume las filas adicionales del conjunto de resultados, aclara el problema de rendimiento.

El planificador de consultas no sugiere índices cuando TOP 1está presente. (en desarrollo).

Cambiar la consulta y arreglar la aplicación está en progreso. La implementación lleva un tiempo.

Mi pregunta: ¿hay alguna forma accesible para DBA de ajustar o ajustar la instancia de SQL Server de producción para superar este problema antes de que la aplicación cambie con la nueva consulta?

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg ON apg.person_id = bi.person_id
  JOIN pplan ON pplan.plan_id = sub.plan_id
  JOIN product ON product.product_id = [plan].product_id 
  JOIN product_attribute ON product_attribute.product_id = product.product_id 
 WHERE apg.group_id = @Id
   AND apg.start_date < GETDATE()
   AND (apg.end_date IS NULL OR apg.end_date > GETDATE()) 
   AND (sub.end_date IS NULL OR sub.end_date > GETDATE()) 
   AND product_attribute.attribute_type = 'special feature' 
   AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;
O. Jones
fuente
¿Lo has probado como una subconsulta? Por ejemplo, seleccione el top 1 ID de suscripción de (seleccione [el resto de su consulta sin el top1]
SeanR
¿Quizás funcionaría un ajuste de consulta "normal"? Si los índices son lo suficientemente atractivos, los escaneos desaparecen. Eso es menos invasivo que una guía de plan.
Usr
Entonces, ¿los mismos valores de @ID siempre lo hacen "volverse loco"? Si es así, pruebe con uno de esos valores y capture el plan de consulta real. Eso te dirá lo que va mal. Si los valores "incorrectos" no son consistentes, entonces es probable que se trate de la detección de parámetros (consulte la respuesta de @ MartinSmith para la solución), o bien un problema de bloqueo que implica cómo el cliente realmente solicita y consume el conjunto de resultados.
RBarryYoung

Respuestas:

12

Si no puede cambiar la consulta, puede usar una guía de plan.

Pruebe el rendimiento de la consulta con OPTION (QUERYTRACEON 4138)(necesitará a alguien con sysadminpermisos para probar esto).

Si eso produce un rendimiento satisfactorio, puede aplicar esto con una guía de plan. Si no produce un rendimiento satisfactorio, intente encontrar una pista que lo haga. Posiblemente OPTION (HASH JOIN, MERGE JOIN)si el problema es bucles anidados inapropiados. Es posible que deba recurrir a la USE PLAN N'...'pista.

Una vez que sepa las sugerencias requeridas, puede aplicarlas utilizando la información aquí .

Martin Smith
fuente
OPTION (QUERYTRACEON 4138)Hizo el truco. Gracias. Ahora a clasificar las guías de plan.
O. Jones
0

para sonrisas, pruebe esto
>> se cambia a> = así que no es exactamente la misma consulta

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi 
        ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg 
        ON apg.person_id = bi.person_id 
       AND apg.group_id = @Id
       AND apg.start_date < GETDATE()
       AND isnnull(apg.end_date, GETDATE()) >= GETDATE()             
  JOIN pplan 
        ON pplan.plan_id = sub.plan_id
       AND isnnull(sub.end_date, GETDATE()) >= GETDATE()
  JOIN product 
        ON product.product_id = [plan].product_id 
  JOIN product_attribute 
        ON product_attribute.product_id = product.product_id 
       AND product_attribute.attribute_type = 'special feature' 
       AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;
paparazzo
fuente
"El cambio de la consulta y la reparación de la aplicación están en progreso. La implementación demora un tiempo". El OP está buscando una solución que corrija el rendimiento "tal cual".
Martin Smith
@ MartininSmith Y cuando lancen una solución, esta puede ser una solución mejor. Hacer que la aplicación consuma las filas adicionales será otro cambio de programa.
paparazzo