Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cette rubrique traite de certains des choix de conception qui améliorent les performances de l’intégration de Microsoft SQL Server à Microsoft .NET Framework Common Language Runtime (CLR).
Processus de compilation
Lors de la compilation d’expressions SQL, lorsqu’une référence à une routine managée est rencontrée, un stub MSIL (Microsoft Intermediate Language) est généré. Ce stub inclut du code pour marshaler les paramètres de routine de SQL Server vers le CLR, appeler la fonction et retourner le résultat. Ce code « glue » est basé sur le type de paramètre et sur le sens du paramètre (in, out ou reference).
Le code de collage permet des optimisations spécifiques au type et garantit une application efficace de la sémantique SQL Server, telle que la possibilité de nullabilité, la contrainte des facettes, la gestion des exceptions par valeur et standard. En générant le code pour les types exacts des arguments, vous évitez le conflit de types ou les coûts de création d'objet de wrapper (ou « conversion boxing ») à travers la limite d'appel.
Le stub généré est ensuite compilé en code natif et optimisé pour l’architecture matérielle particulière sur laquelle SQL Server s’exécute, à l’aide des services de compilation JIT (juste-à-temps) du CLR. Les services JIT sont appelés au niveau de la méthode et permettent à l’environnement d’hébergement SQL Server de créer une unité de compilation unique qui s’étend à la fois sur SQL Server et l’exécution du CLR. Une fois le stub compilé, le pointeur fonction résultant devient l'implémentation à l'exécution de la fonction. Cette approche de génération de code garantit qu’il n’existe aucun coût d’appel supplémentaire lié à la réflexion ou à l’accès aux métadonnées au moment de l’exécution.
Transitions rapides entre SQL Server et CLR
Le processus de compilation génère une fonction pointeur qui peut être appelée au moment de l'exécution à partir du code natif. Dans le cas de fonctions scalaires définies par l’utilisateur, cet appel de fonction se produit sur une base par ligne. Pour réduire le coût de la transition entre SQL Server et le CLR, les instructions qui contiennent n’importe quel appel managé ont une étape de démarrage pour identifier le domaine d’application cible. Cette étape d'identification réduit le coût de la transition pour chaque ligne.
Considérations relatives aux performances
L’exemple suivant récapitule les considérations relatives aux performances spécifiques à l’intégration clR dans SQL Server. Vous trouverez des informations plus détaillées dans « Utilisation de l’intégration CLR dans SQL Server 2005 » sur le site web MSDN. Vous trouverez des informations générales sur les performances du code managé dans « Amélioration des performances et de l’évolutivité des applications .NET » sur le site web MSDN.
Fonctions définies par l'utilisateur
Les fonctions CLR bénéficient d’un chemin d’appel plus rapide que celui de Transact-SQL fonctions définies par l’utilisateur. En outre, le code managé présente un avantage décisif sur Transact-SQL en termes de code, de calcul et de manipulation de chaînes. Les fonctions CLR nécessitant beaucoup d’informations et qui n’effectuent pas d’accès aux données sont mieux écrites dans le code managé. Toutefois, les fonctions Transact-SQL effectuent un accès aux données plus efficacement que l’intégration CLR.
Agrégats définis par l'utilisateur
Le code managé se révèle considérablement plus performant que l'agrégation à base de curseur. Le code managé effectue généralement un peu plus lent que les fonctions d’agrégation SQL Server intégrées. S'il existe une fonction d'agrégation intégrée native, il est recommandé de l'utiliser. Dans les cas où l’agrégation nécessaire n’est pas prise en charge en mode natif, considérez un agrégat CLR défini par l’utilisateur sur une implémentation basée sur un curseur pour des raisons de performances.
Fonctions de diffusion en continu Table-Valued
Les applications doivent souvent retourner une table comme résultat de l'appel d'une fonction. Les exemples incluent la lecture de données tabulaires à partir d'un fichier dans le cadre d'une opération d'importation et la conversion de valeurs séparées par des virgules dans le cas d'une représentation relationnelle. En général, vous pouvez accomplir ces actions en matérialisant la table de résultats et en la remplissant avant qu'elle ne puisse être consommée par l'appelant. L’intégration du CLR à SQL Server introduit un nouveau mécanisme d’extensibilité appelé fonction table de diffusion en continu (STVF). Les fonctions table en continu offrent de meilleures performances que les implémentations de procédure stockée étendue comparables.
Les fonctions table en continu sont des fonctions managées qui retournent une interface IEnumerable.
IEnumerable possède des méthodes pour se déplacer à travers le jeu de résultats retourné par la fonction table en continu. Lorsque la fonction table en continu est appelée, l'interface IEnumerable retournée est directement connectée au plan de requête. Le plan de requête appelle les méthodes IEnumerable lorsqu'il doit extraire des lignes. Ce modèle d'itération permet que les résultats soient consommés immédiatement après que la première ligne a été créée, au lieu d'attendre que la totalité de la table soit remplie. Il réduit aussi considérablement la mémoire consommée en appelant la fonction.
Tableaux et curseurs
Lorsque les curseurs Transact-SQL doivent parcourir les données plus facilement exprimées sous forme de tableau, le code managé peut être utilisé avec des gains de performances significatifs.
Données de chaîne
Les données de caractères SQL Server, telles que varchar, peuvent être de type SqlString ou SqlChars dans les fonctions managées. Les variables SqlString créent une instance de la valeur entière en mémoire. Les variables SqlChars fournissent une interface de diffusion en continu qui peut être utilisée pour améliorer les performances et l’extensibilité en ne créant pas d’instance de la valeur entière en mémoire. Cela devient particulièrement important pour les données d’objet volumineux (LOB). En outre, il est possible d'accéder aux données XML du serveur via une interface de diffusion retournée par SqlXml.CreateReader().
CLR et procédures stockées étendues
Les interfaces de programmation d’applications Microsoft.SqlServer.Server (API) qui permettent aux procédures managées d’envoyer des jeux de résultats au client fonctionnent mieux que les API Open Data Services (ODS) utilisées par des procédures stockées étendues. En outre, les API System.Data.SqlServer prennent en charge les types de données tels que xml, varchar(max), nvarchar(max)et varbinary(max), introduits dans SQL Server 2005 (9.x), tandis que les API ODS n’ont pas été étendues pour prendre en charge les nouveaux types de données.
Avec le code managé, SQL Server gère l’utilisation de ressources telles que la mémoire, les threads et la synchronisation. Cela est dû au fait que les API managées qui exposent ces ressources sont implémentées sur le gestionnaire de ressources SQL Server. À l’inverse, SQL Server n’a pas de vue ou de contrôle sur l’utilisation des ressources de la procédure stockée étendue. Par exemple, si une procédure stockée étendue consomme trop de ressources processeur ou mémoire, il n’existe aucun moyen de détecter ou de contrôler cela avec SQL Server. Toutefois, avec le code managé, SQL Server peut détecter qu’un thread donné n’a pas généré pendant une longue période, puis forcer la tâche à générer afin que d’autres travaux puissent être planifiés. Par conséquent, l’utilisation du code managé offre une meilleure scalabilité et une meilleure utilisation des ressources système.
Le code managé peut entraîner une surcharge supplémentaire nécessaire pour maintenir l’environnement d’exécution et effectuer des vérifications de sécurité. C’est le cas, par exemple, lors de l’exécution à l’intérieur de SQL Server et de nombreuses transitions entre le code managé et le code natif sont requises (car SQL Server doit effectuer une maintenance supplémentaire sur les paramètres spécifiques au thread lors du passage au code natif et au retour). Par conséquent, les procédures stockées étendues peuvent considérablement surperformer le code managé s’exécutant à l’intérieur de SQL Server pour les cas où il existe des transitions fréquentes entre le code managé et natif.
Remarque
Il est recommandé de ne pas développer de nouvelles procédures stockées étendues, car cette fonctionnalité a été déconseillée.
Sérialisation native pour les types User-Defined
Les types définis par l'utilisateur (UDT) sont conçus comme mécanisme d'extensibilité du système de types scalaires. SQL Server implémente un format de sérialisation pour les UDT appelés Format.Native. Pendant la compilation, la structure du type est examinée pour générer MSIL personnalisée pour cette définition de type particulière.
La sérialisation native est l’implémentation par défaut pour SQL Server. La sérialisation définie par l'utilisateur appelle une méthode définie par le créateur du type pour effectuer la sérialisation. La sérialisation Format.Native doit être utilisée si possible pour de meilleures performances.
Normalisation des UDT comparables
Les opérations relationnelles, telles que le tri et la comparaison d'UDT, fonctionnent directement sur la représentation binaire de la valeur. Cette tâche s'effectue en stockant une représentation normalisée (classement binaire) de l'état de l'UDT sur le disque.
La normalisation présente deux avantages : elle rend l’opération de comparaison considérablement moins coûteuse en évitant la construction de l’instance de type et la surcharge d’appel de méthode ; et il crée un domaine binaire pour l’UDT, ce qui permet la construction d’histogrammes, d’index et d’histogrammes pour les valeurs du type. Par conséquent, les UDT normalisés ont un profil de performances très similaire aux types intégrés natifs pour les opérations qui n’impliquent pas d’appel de méthode.
Utilisation évolutive de la mémoire
Pour que le garbage collection managé fonctionne correctement dans SQL Server, évitez une allocation unique volumineuse. Les allocations supérieures à 88 kilo-octets (Ko) sont placées sur le tas d’objets volumineux, ce qui entraîne l’exécution et la mise à l’échelle d’un garbage collection beaucoup plus mauvais que de nombreuses allocations plus petites. Par exemple, si vous avez besoin d’allouer un tableau multidimensionnel volumineux, il est préférable d’allouer un tableau en jaquet (éparpillé).