Share via


Arquitectura de integración de CLR: rendimiento

Se aplica a:SQL ServerAzure SQL Managed Instance

En este tema se describen algunas de las opciones de diseño que mejoran el rendimiento de Microsoft SQL Server integración con Common Language Runtime (CLR) de Microsoft .NET Framework.

El proceso de compilación

Durante la compilación de expresiones SQL, cuando se encuentra una referencia a una rutina administrada, se genera un código auxiliar del lenguaje intermedio de Microsoft (MSIL). Este código auxiliar incluye código para serializar los parámetros de rutina de SQL Server a CLR, invocar la función y devolver el resultado. Este código de "unión" está basado en el tipo y la dirección del parámetro (entrada, salida o referencia).

El código de pegamento permite optimizaciones específicas del tipo y garantiza una aplicación eficaz de la semántica de SQL Server, como la nulabilidad, las facetas restringidas, el control de excepciones estándar y por valor. Al generar código para los tipos exactos de los argumentos, se evitan los costos de la conversión de tipos o de la creación de objetos contenedores (denominada "conversión boxing") dentro de los límites de la invocación.

A continuación, el código auxiliar generado se compila en código nativo y se optimiza para la arquitectura de hardware concreta en la que se ejecuta SQL Server, mediante los servicios de compilación JIT (Just-In-Time) de CLR. Los servicios JIT se invocan en el nivel de método y permiten que el entorno de hospedaje de SQL Server cree una sola unidad de compilación que abarque tanto SQL Server como la ejecución de CLR. Una vez compilado el código auxiliar, el puntero resultante a la función se convierte en la implementación de la función durante la ejecución. Este enfoque de generación de código garantiza que no haya ningún costo de invocación adicional relacionado con el acceso a los metadatos o el reflejo durante la ejecución.

Transiciones rápidas entre SQL Server y CLR

El proceso de compilación produce un puntero a función al que se puede llamar durante la ejecución desde código nativo. En el caso de funciones definidas por el usuario con valores escalares, esta invocación de función se produce fila por fila. Para minimizar el costo de la transición entre SQL Server y CLR, las instrucciones que contienen cualquier invocación administrada tienen un paso de inicio para identificar el dominio de aplicación de destino. Este paso de identificación reduce el costo de la transición para cada fila.

Consideraciones de rendimiento

A continuación se resumen las consideraciones de rendimiento específicas de la integración de CLR en SQL Server. Puede encontrar información más detallada en "Using CLR Integration in SQL Server 2005" (Usar la integración CLR en SQL Server 2005) en el sitio web de MSDN. Puede encontrar información general sobre el rendimiento del código administrado en "Mejorar el rendimiento y la escalabilidad de aplicaciones .NET" en el sitio web de MSDN.

Funciones definidas por el usuario

Las funciones CLR se benefician de una ruta de invocación más rápida que la de las funciones definidas por el usuario de Transact-SQL. Además, el código administrado tiene una ventaja de rendimiento decisiva sobre Transact-SQL en términos de código de procedimientos, cálculo y manipulación de cadenas. Las funciones de CLR que requieren una gran cantidad de cálculo y que no proporcionan acceso a datos se escriben mejor en código administrado. Sin embargo, las funciones de Transact-SQL realizan el acceso a datos de forma más eficaz que la integración con CLR.

Funciones de agregado definidas por el usuario

El código administrado puede mejorar significativamente el rendimiento de la agregación basada en cursor. Por lo general, el código administrado funciona ligeramente más lento que las funciones de agregado integradas SQL Server. Si existe una función de agregado integrada nativa, se recomienda utilizarla. En los casos en que la agregación que se necesita no se admite de forma nativa, piense en utilizar una función de agregado definida por el usuario de CLR en lugar de una implementación basada en cursor para obtener un mejor rendimiento.

Funciones con valores de tabla de transmisión por secuencias

Después de invocar una función, las aplicaciones suelen necesitar devolver una tabla. Entre los ejemplos se incluye la lectura de datos tabulares de un archivo como parte de una operación de importación y la conversión de valores separados por comas en una representación relacional. Normalmente, esto se puede llevar a cabo materializando y rellenando la tabla de resultados antes de que pueda consumirla el autor de las llamadas. La integración de CLR en SQL Server introduce un nuevo mecanismo de extensibilidad denominado función con valores de tabla de streaming (STVF). Las STVF administradas funcionan mejor que las implementaciones de procedimiento almacenado extendido comparables.

Las STVF son funciones administradas que devuelven una interfaz IEnumerable . IEnumerable tiene métodos para navegar por el conjunto de resultados devuelto por STVF. Cuando se invoca STVF, el IEnumerable devuelto se conecta directamente al plan de consulta. El plan de consulta llama a métodos IEnumerable cuando necesita capturar filas. Este modelo de iteración permite utilizar los resultados inmediatamente después de que se genere la primera fila, en lugar de esperar hasta que se rellene la tabla completa. Reduce también significativamente la cantidad de memoria que se utiliza al invocar la función.

Matrices frente a cursores

Cuando los cursores de Transact-SQL deben atravesar los datos que se expresan más fácilmente como una matriz, el código administrado se puede usar con importantes mejoras de rendimiento.

Datos de cadena

SQL Server datos de caracteres, como varchar, pueden ser del tipo SqlString o SqlChars en funciones administradas. Las variables SqlString crean una instancia del valor completo en la memoria. Las variables SqlChars proporcionan una interfaz de transmisión por secuencias que se puede utilizar para lograr mejores rendimiento y escalabilidad sin crear una instancia del valor completo en la memoria. Esto se vuelve especialmente importante para los datos de objetos grandes (LOB). Además, se puede acceder a los datos XML del servidor a través de una interfaz de streaming devuelta por SqlXml.CreateReader().

CLR frente a los procedimientos almacenados extendidos

Las interfaces de programación de aplicaciones (API) de Microsoft.SqlServer.Server que permiten a los procedimientos administrados devolver conjuntos de resultados al cliente funcionan mejor que las API de Servicios abiertos de datos (ODS) utilizadas por los procedimientos almacenados extendidos. Además, las API System.Data.SqlServer admiten tipos de datos como xml, varchar(max), nvarchar(max) y varbinary(max), introducidos en SQL Server 2005 (9.x), mientras que las API ods no se han ampliado para admitir los nuevos tipos de datos.

Con el código administrado, SQL Server administra el uso de recursos como memoria, subprocesos y sincronización. Esto se debe a que las API administradas que exponen estos recursos se implementan sobre el administrador de recursos de SQL Server. Por el contrario, SQL Server no tiene ninguna vista ni control sobre el uso de recursos del procedimiento almacenado extendido. Por ejemplo, si un procedimiento almacenado extendido consume demasiados recursos de CPU o memoria, no hay ninguna manera de detectarlo o controlarlo con SQL Server. Sin embargo, con el código administrado, SQL Server puede detectar que un subproceso determinado no se ha producido durante un largo período de tiempo y, a continuación, forzar el rendimiento de la tarea para que se pueda programar otro trabajo. Por consiguiente, el uso de código administrado aporta una mayor escalabilidad y una mejor utilización de los recursos del sistema.

El código administrado puede hacer que se produzca una sobrecarga adicional necesaria para mantener el entorno de ejecución y realizar comprobaciones de seguridad. Este es el caso, por ejemplo, cuando se ejecuta dentro de SQL Server y se requieren numerosas transiciones de código administrado a nativo (porque SQL Server debe realizar un mantenimiento adicional en la configuración específica del subproceso al pasar al código nativo y atrás). Por lo tanto, los procedimientos almacenados extendidos pueden superar significativamente el código administrado que se ejecuta dentro de SQL Server en los casos en los que hay transiciones frecuentes entre código administrado y nativo.

Nota

No se recomienda desarrollar nuevos procedimientos almacenados extendidos, puesto que esta característica ha quedado desusada.

Serialización nativa para los tipos definidos por el usuario

Los tipos definidos por el usuario (UDT) están diseñados como un mecanismo de extensibilidad para el sistema de tipo escalar. SQL Server implementa un formato de serialización para udT denominado Format.Native. Durante la compilación se examina la estructura del tipo para generar el MSIL personalizado para esa definición de tipo concreta.

La serialización nativa es la implementación predeterminada de SQL Server. La serialización definida por el usuario invoca un método definido por el autor de tipo para realizar la serialización. La serialización Format.Native debe usarse siempre que sea posible para obtener el mejor rendimiento.

Normalización de tipos definidos por el usuario comparables

Las operaciones relacionales, como ordenar y comparar tipos definidos por el usuario (UDT), funcionan directamente en la representación binaria del valor. Esto se logra almacenando en disco una representación normalizada (ordenada de forma binaria) del estado del UDT.

La normalización tiene dos ventajas: abarata considerablemente la operación de comparación al evitar la creación de la instancia de tipo y la sobrecarga de la invocación de métodos; y crea un dominio binario para el UDT que permite la creación de histogramas, índices e histogramas para los valores del tipo. Por consiguiente, los UDT normalizados tienen un perfil de rendimiento muy similar al de los tipos integrados nativos para las operaciones que no implican la invocación de métodos.

Uso de memoria escalable

Para que la recolección de elementos no utilizados administrados funcione y escale bien en SQL Server, evite la asignación grande y única. Las asignaciones con un tamaño superior a 88 kilobytes (KB) se colocarán en el montón de objeto grande, lo que hará que la recolección de elementos no utilizados se ejecute y escale mucho peor que muchas asignaciones más pequeñas. Por ejemplo, si necesita asignar una matriz multidimensional grande, es preferible asignar una matriz escalonada (dispersa).

Consulte también

Tipos definidos por el usuario CLR