sql >> Base de Datos >  >> RDS >> Sqlserver

¿Qué puedo hacer para mejorar el rendimiento de mi función definida por el usuario pura en SQL Server?

Mi primer pensamiento aquí es:¿cuál es el problema de rendimiento? Seguro que tiene un bucle (una vez por fila para aplicar dónde) dentro de un bucle que ejecuta una consulta. Pero, ¿está obteniendo planes de ejecución deficientes? ¿Son enormes sus conjuntos de resultados? Pero volvamos a lo genérico. ¿Cómo resuelve una vez este problema? SQL realmente no memoriza (como señala el ilustre @Martin_Smith). Entonces, ¿qué debe hacer un chico?

Opción 1:nuevo diseño

Crea un diseño completamente nuevo. En este caso específico, @Aaron_Bertrand señala que una tabla de calendario puede satisfacer sus necesidades. Muy bien. Esto realmente no lo ayuda con situaciones que no son de calendario, pero como suele ser el caso en SQL, debe pensar un poco diferente.

Opción 2 - Llame a la UDF Menos

Limite el conjunto de elementos que llaman a esta función. Esto me recuerda mucho cómo hacer paginación/recuento de filas . Genere un pequeño conjunto de resultados que tenga los distintos valores requeridos y luego llame a su UDF para que solo se llame unas pocas veces. Esto puede o no ser una opción, pero puede funcionar en muchos escenarios.

Opción 3:UDF dinámico

Probablemente me sacarán abucheado de la sala por esta sugerencia, pero aquí va. Lo que hace que este UDF sea lento es la declaración de selección dentro del ciclo. Si su tabla de vacaciones realmente cambia con poca frecuencia, podría poner un disparador en la tabla. El disparador escribiría y actualizaría UDF. El nuevo UDF podría aplicar la fuerza bruta en todas las decisiones de vacaciones. ¿Sería un poco como el canibalismo con SQL escribiendo SQL? Por supuesto. Pero eliminaría la subconsulta y aceleraría el UDF. Que comiencen los abucheos.

Opción 4 - Memorízalo!

Si bien SQL no puede memorizar directamente, tenemos SQL CLR. Convierta la UDF en una udf SQL CLR. En CLR puedes usar variables estáticas. Puede tomar fácilmente la tabla Holidays a intervalos regulares y almacenarlos en una tabla hash. Luego simplemente reescriba su ciclo en el CLR. Incluso podría ir más allá y memorizar la respuesta completa si esa es la lógica apropiada.

Actualización:

Opción 1:realmente estaba tratando de concentrarme en lo general aquí, no en la función de ejemplo que usó anteriormente. Sin embargo, el diseño actual de su UDF permite múltiples llamadas a la tabla de vacaciones si golpea varias seguidas. El uso de algún tipo de tabla de estilo de calendario que contenga una lista de "días malos" y el "próximo día hábil" correspondiente le permitirá eliminar la posibilidad de múltiples aciertos y consultas.

Opción 3:si bien el dominio es desconocido de antemano, es muy posible que modifique su tabla de vacaciones. Para un día festivo dado, contendría el siguiente día laborable correspondiente. A partir de estos datos, podría escupir un UDF con una declaración de caso larga (cuando '5/5/2012' luego '5/14/2012' o algo similar) en la parte inferior. Es posible que esta estrategia no funcione para todos los tipos de problemas, pero podría funcionar bien para algunos tipos de problemas.

Opción 4 - Hay implicaciones para cada tecnología. Es necesario implementar CLR, modificar la configuración de SQL Server y SQL CLR está limitado al marco 3.5. Personalmente, he encontrado estos ajustes bastante fáciles, pero su situación puede ser diferente (por ejemplo, un DBA recalcitrante o restricciones en las modificaciones a los servidores de producción).

El uso de variables estáticas requiere los ensamblajes be CONFIANZA PLENA . Tendrá que asegurarse de obtener el bloqueo correcto.

Hay algunas pruebas que en muy alto niveles de transacción CLR no funciona tan bien como SQL directo. Sin embargo, en su escenario, esta observación podría no ser aplicable porque no hay un correlato directo de SQL para lo que está tratando de hacer (memoizar).