Après avoir lu l'article suivant, j'ai trouvé que le test de l'auteur est vraiment utile aux amis qui utilisent ASP. Il devrait être similaire non seulement pour ASP mais pour d'autres langages. La génération de contenu dynamique sur le serveur est l'une des principales raisons d'utiliser ASP. Le premier projet de test que nous avons choisi était donc de déterminer la meilleure méthode pour envoyer du contenu dynamique au flux de réponse. Il existe deux options de base (et quelques variantes) : l'utilisation de balises ASP en ligne et l'utilisation de l'instruction Response.Write.
Pour tester ces différentes approches, nous avons créé une simple page ASP qui définissait certaines variables puis les insérait dans un tableau. Bien que cette page soit simple et sans utilité pratique, elle suffit à nous permettre d'isoler et de tester des problèmes individuels.
2.1 Utilisation des balises en ligne ASP
Le premier test consiste à utiliser la balise en ligne d'ASP <%= x %>, où x est une variable. Il s’agit de la méthode la plus pratique à utiliser et elle rend la partie HTML de la page plus facile à lire et à gérer.
Copiez le code comme suit :
<% OPTION EXPLICITE
Dim Prénom
DimLastName
Faible milieuInitial
Dim Adresse
Ville sombre
État sombre
FaibleNuméro de téléphone
Faxer le numéro de fax
Faible E-mail
DimDate de naissance
Prénom = Jean
MilieuInitial = Q
Nom = Public
Adresse = 100, rue Main
Ville = New York
État = New York
Numéro de téléphone = 1-212-555-1234
Numéro de fax = 1-212-555-1234
E-mail = [email protected]
Date de naissance = 1/1/1950
%>
<HTML>
<TÊTE>
<TITLE>Test de réponse</TITLE>
</HEAD>
<CORPS>
<H1>Test de réponse</H1>
<TABLE>
<tr><td><b>Prénom :</b></td><td><%= Prénom %></td></tr>
<tr><td><b>Initiale du milieu :</b></td><td><%= MiddleInitial %></td></tr>
<tr><td><b>Nom :</b></td><td><%= Nom %></td></tr>
<tr><td><b>Adresse :</b></td><td><%= Adresse %></td></tr>
<tr><td><b>Ville :</b></td><td><%= Ville %></td></tr>
<tr><td><b>État :</b></td><td><%= État %></td></tr>
<tr><td><b>Numéro de téléphone :</b></td><td><%= PhoneNumber %></td></tr>
<tr><td><b>Numéro de fax :</b></td><td><%= FaxNumber %></td></tr>
<tr><td><b>EMail :</b></td><td><%= EMail %></td></tr>
<tr><td><b>Date de naissance :</b></td><td><%= BirthDate %></td></tr>
</TABLE>
</CORPS>
</HTML>
Le code complet de /app1/response1.asp
Meilleur enregistrement = 8,28 ms/page
2.2 Utilisez Response.Write pour afficher chaque ligne de code HTML
Il existe de nombreuses bonnes publications qui indiquent que l'approche de balisage en ligne précédente doit être évitée car elle entraîne une opération appelée changement de contexte. Cette opération se produit lorsque le type de code traité par le serveur Web change (de l'envoi de HTML pur au traitement de script, ou vice versa), et ce changement prend un certain temps. Une fois que de nombreux programmeurs ont appris cela, leur première réaction est d'utiliser la fonction Response.Write pour afficher chaque ligne de code HTML :
Copiez le code comme suit :
...
Réponse.Write(<html>)
Réponse.Write(<head>)
Response.Write( <title>Test de réponse</title>)
Réponse.Write(</head>)
Réponse.Write(<corps>)
Response.Write(<h1>Test de réponse</h1>)
Réponse.Write(<table>)
Response.Write(<tr><td><b>Prénom :</b></td><td> & Prénom & </td></tr>)
Response.Write(<tr><td><b>Initiale du milieu :</b></td><td> & MiddleInitial & </td></tr>)
...
Fragment /app1/response2.asp
Meilleur enregistrement = 8,28 ms/page
Temps de réponse = 8,08 ms/page
Différence = -0,20 ms (réduction de 2,4%)
L’amélioration des performances que nous avons constatée par rapport à la version de balisage en ligne était si faible qu’elle était tout simplement surprenante. Cela peut être dû au fait qu'il y a beaucoup plus d'appels de fonction dans la page. Cependant, cette méthode présente un inconvénient plus important étant donné que le code HTML est intégré à la fonction, le code du script devient très long et peu pratique à lire et à maintenir.
2.3 Utiliser les fonctions wrapper
Response.Write n'ajoute pas CRLF (Carriage Return - Line Feed, Carriage Return - Line Feed) à la fin de la ligne de texte, ce qui est l'aspect le plus décevant de l'utilisation de la méthode ci-dessus. Bien que le code HTML ait été bien formaté côté serveur, ce que vous voyez dans le navigateur n’est toujours qu’une longue ligne de code. Mais ce problème n’a pas été la seule déception. Les gens ont vite découvert qu’il n’existait pas de fonction Response.WriteLn capable d’ajouter automatiquement du CRLF. Une réaction naturelle consiste à créer une fonction wrapper pour Response.Write et à ajouter CRLF après chaque ligne :
...
writeCR(<tr><td><b>Prénom :</b></td><td> & Prénom & </td></tr>)
...
SUB écrireCR(str)
Réponse.Write(str & vbCRLF)
FIN SOUS
Fragment /app1/response4.asp
Meilleur enregistrement = 8,08 ms/page
Temps de réponse = 10,11 ms/page
Différence = +2,03 ms (augmentation de 25,1 %)
Le résultat est une diminution significative des performances. Bien sûr, cela est principalement dû au fait que cette méthode double le nombre d'appels de fonction et que son impact sur les performances est très évident. Cette utilisation est à éviter à tout prix, CRLF entraîne deux octets supplémentaires à la fin de chaque ligne, et ces deux octets sont inutiles au navigateur pour afficher la page. Dans la plupart des cas, le beau format du code HTML côté navigateur permet simplement à vos concurrents de lire et de comprendre plus facilement la conception de la page.
2.4 Fusionner plusieurs Response.Write
En ignorant le dernier test sur l'encapsulation des fonctions, la prochaine étape logique serait de fusionner toutes les chaînes d'instructions Response.Write distinctes en une seule instruction, réduisant ainsi le nombre d'appels de fonction et améliorant l'efficacité du code.
Copiez le code comme suit :
Réponse.Write(<html> & _
<tête> & _
<title>Test de réponse</title> & _
</tête> & _
<corps> & _
<h1>Test de réponse</h1> & _
<table> & _
<tr><td><b>Prénom :</b></td><td> & Prénom & </td></tr> & _
...
<tr><td><b>Date de naissance :</b></td><td> & Date de naissance & </td></tr> & _
</table> & _
</corps> & _
</html>)
Fragment /app1/response3.asp
Meilleur enregistrement = 8,08 ms/page
Temps de réponse = 7,05 ms/page
Différence = -1,03 ms (réduction de 12,7 %)
C'est de loin la meilleure méthode.
2.5 Combinez plusieurs Response.Write et ajoutez CRLF à la fin de chaque ligne
Certaines personnes sont également très soucieuses de savoir si leur code HTML est beau du côté du navigateur, nous ajoutons donc un retour chariot à la fin de chaque ligne de code HTML, en utilisant la constante vbCRLF. Les autres codes de test sont les mêmes que dans l'exemple ci-dessus. .
...
Réponse.Write(<html> & vbCRLF & _
<tête> & vbCRLF & _
<title>Test de réponse</title> & vbCRLF & _
</head> & vbCRLF & _
...
Fragment /app1/response5.asp
Meilleur enregistrement = 7,05 ms/page
Temps de réponse = 7,63 ms/page
Différence = +0,58 ms (augmentation de 8,5%)
Le résultat est une légère diminution des performances, probablement due à l'ajout d'opérations de concaténation de chaînes et à l'augmentation du texte de sortie.
2.6 Commentaires
Sur la base des résultats du test de sortie ASP ci-dessus, nous arrivons aux règles de codage suivantes :
Évitez d’utiliser trop d’ASP intégré.
Combinez autant d’instructions Response.Write que possible en une seule instruction.
N’encapsulez jamais Response.Write juste pour ajouter CRLF.
Si vous souhaitez formater la sortie HTML, ajoutez CRLF directement après l'instruction Response.Write.
Aperçu : Quel est le moyen le plus efficace de générer du contenu généré dynamiquement par ASP ? Quelle est la meilleure façon d’extraire un jeu d’enregistrements de base de données ? Cet article teste près de 20 problèmes courants dans un tel développement ASP. Le temps affiché par l'outil de test nous l'indique : ces problèmes qui sont généralement considérés comme acquis sont non seulement dignes d'attention, mais cachent également des secrets inattendus.
1. Objectif du test
La première partie de cet article examine certains problèmes fondamentaux du développement ASP et donne des résultats de tests de performances pour aider les lecteurs à comprendre l'impact du code placé sur la page sur les performances. ADO est une interface de base de données universelle et facile à utiliser développée par Microsoft. Il s'avère que l'interaction avec la base de données via ADO est l'une des applications les plus importantes d'ASP. Dans la deuxième partie, nous étudierons cette question.
Les fonctionnalités fournies par ADO sont assez étendues, la plus grande difficulté lors de la préparation de cet article est donc de savoir comment définir l'étendue du problème. Considérant que l'extraction de grandes quantités de données peut augmenter considérablement la charge sur le serveur Web, nous avons décidé que l'objectif principal de cette section est de découvrir quelle est la configuration optimale pour faire fonctionner les jeux d'enregistrements ADO. Cependant, même après avoir réduit la portée du problème, nous sommes toujours confrontés à de grandes difficultés, car ADO peut disposer de nombreuses manières différentes pour accomplir la même tâche. Par exemple, les jeux d'enregistrements peuvent être extraits non seulement via la classe Recordset, mais également via les classes Connection et Command, même après avoir obtenu l'objet Recordset, il existe de nombreuses méthodes d'opération qui peuvent affecter considérablement les performances ; Cependant, comme dans la première partie, nous tenterons de couvrir l’éventail le plus large possible de problématiques.
Plus précisément, l'objectif de cette section est de rassembler suffisamment d'informations pour répondre aux questions suivantes :
ADOVBS.inc doit-il être référencé via include ?
lDois-je créer un objet de connexion distinct lors de l'utilisation de jeux d'enregistrements ?
lQuelle est la meilleure façon d’extraire un jeu d’enregistrements ?
lQuel type de curseur et quelle méthode de verrouillage d'enregistrement sont les plus efficaces ?
lDois-je utiliser un jeu d'enregistrements local ?
lQuelle est la meilleure façon de définir les propriétés du jeu d'enregistrements ?
lQuelle méthode est la plus efficace pour référencer les valeurs de champ dans un jeu d'enregistrements ?
lEst-ce un bon moyen de collecter la sortie avec une chaîne temporaire ?
2. Environnement de test
Au total, 21 fichiers ASP ont été utilisés dans ce test, qui peuvent être téléchargés à la fin de cet article. Chaque page est configurée pour exécuter trois requêtes différentes, renvoyant respectivement 0, 25 et 250 enregistrements. Cela nous aidera à isoler la surcharge d'initialisation et d'exécution de la page elle-même de la surcharge de boucle dans le jeu d'enregistrements.
Pour faciliter les tests, la chaîne de connexion à la base de données et la chaîne de commande SQL sont enregistrées en tant que variables d'application dans Global.asa. Étant donné que notre base de données de test est SQL Server 7.0, la chaîne de connexion spécifie OLEDB comme fournisseur de connexion et les données de test proviennent de la base de données Northwind de SQL Server. La commande SQL SELECT extrait 7 champs spécifiés de la table NorthWind Orders.
Copiez le code comme suit :
<SCRIPT LANGUAGE=VBScript RUNAT=Serveur>
Sous-application_OnStart
Application (Conn) = Fournisseur = SQLOLEDB ;
Serveur=MonServeur ;
uid=sa;
mot de passe=;
BASE DE DONNÉES=vent du nord
Application (SQL) = SELECTTOP 0OrderID, & _
ID client, & _
ID d'employé, & _
Date de commande, & _
Date requise, & _
Date d'expédition, & _
Fret & _
DE[Commandes]
Fin du sous-marin
</SCRIPT>
'SQL alternatif - 25 enregistrements
Application (SQL) = SELECTTOP 25OrderID, & _
ID client, & _
ID d'employé, & _
Date de commande, & _
Date requise, & _
Date d'expédition, & _
Fret & _
DE[Commandes]
'enregistrements sql-250 alternatifs
Application (SQL) = SELECTTOP 250 ID de commande, & _
ID client, & _
ID d'employé, & _
Date de commande, & _
Date requise, & _
Date d'expédition, & _
Fret & _
DE[Commandes]
La configuration du serveur de test était la suivante : Pentium 450 MHz, 512 Mo de RAM, NT Server 4.0 SP5, MDAC 2.1 (Data Access Component) et Microsoft Scripting Engine version 5.0. SQL Server s'exécute sur une autre machine avec une configuration similaire. Comme dans la première partie, nous utilisons toujours Microsoft Web Application Stress Tool pour enregistrer le temps écoulé entre la première requête de page et le dernier octet reçu du serveur (TTLB, Time To Last Byte), le temps est en millisecondes. Le script de test a appelé chaque page plus de 1 300 fois et a pris environ 20 heures pour s'exécuter. Les temps indiqués ci-dessous correspondent au TTLB moyen pour la session. N'oubliez pas que, comme dans la première partie, nous ne nous préoccupons que de l'efficacité du code, et non de son évolutivité ou des performances du serveur.
Notez également que nous avons activé la mise en mémoire tampon du serveur. De plus, afin que tous les noms de fichiers aient la même longueur, certains noms de fichiers contiennent un ou plusieurs traits de soulignement.
3. Premier essai
Dans le premier test, nous avons extrait un jeu d'enregistrements simulant un scénario typique trouvé dans les exemples Microsoft ASP ADO. Dans cet exemple (ADO__01.asp), nous ouvrons d’abord une connexion, puis créons l’objet recordset. Bien entendu, le script ici est optimisé selon les règles de codage résumées dans la première partie de cet article.
Copiez le code comme suit :
<% Option explicite %>
<!-- #Include file=ADOVBS.INC -->
<%
Dim objConn
Dim objRS
Réponse.Write(_
<HTML><TÊTE> & _
<TITLE>Test ADO</TITLE> & _
</TÊTE><CORPS> _
)
Définir objConn = Server.CreateObject (ADODB.Connection)
objConn.Ouvrir l'application (Conn)
Définir objRS = Server.CreateObject (ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = adOpenForwardOnly
objRS.LockType = adLockReadOnly
objRS.Application ouverte (SQL)
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire des titres
Réponse.Write(_
<BORDURE TABLE=1> & _
<TR> & _
<TH>ID de commande</TH> & _
<TH>IDClient</TH> & _
<TH>ID de l'employé</TH> & _
<TH>Date de commande</TH> & _
<TH>Date requise</TH> & _
<TH>Date d'expédition</TH> & _
<TH>Fret</TH> & _
</TR> _
)
'écrire des données
Faire sans objRS.EOF
Réponse.Write(_
<TR> & _
<TD> & objRS(Commande) & </TD> & _
<TD> & objRS(IDClient) & </TD> & _
<TD> & objRS(IDEmployé) & </TD> & _
<TD> & objRS(DateCommande) & </TD> & _
<TD> & objRS(RequiredDate) & </TD> & _
<TD> & objRS(DateExpédition) & </TD> & _
<TD> & objRS(Fret) & </TD> & _
</TR> _
)
objRS.MoveNext
Boucle
Réponse.Write(</TABLE>)
Fin si
objRS.Fermer
objConn.Fermer
Définir objRS = Rien
Définir objConn = Rien
Réponse.Write(</BODY></HTML>)
%>
Voici les résultats des tests :
Jetons un coup d'œil à la signification des nombres dans chaque colonne :
0 renvoie le TTLB (en millisecondes) requis pour une page de 0 enregistrements. Dans tous les tests, cette valeur est considérée comme le temps nécessaire à la génération de la page elle-même (y compris la création d'objets), à l'exclusion du temps d'itération dans les données du jeu d'enregistrements.
25 TTLB en millisecondes pour récupérer et afficher 25 enregistrements
Le TTLB dans la colonne temps total/2 525 est divisé par 25, ce qui correspond au coût de temps moyen total par enregistrement.
temps d'affichage/2525 colonne TTLB moins 0 colonne TTLB, puis divisez par 25. Cette valeur reflète le temps requis pour afficher un seul enregistrement tout en parcourant le jeu d'enregistrements.
250 Extrait et affiche le TTLB de 250 enregistrements.
Le TTLB dans la colonne tot time/250250 est divisé par 25. Cette valeur représente le coût en temps moyen total d'un seul enregistrement.
disp time/250 Le TTLB de la colonne 250 est soustrait du TTLB de la colonne 0, puis divisé par 250. Cette valeur reflète le temps requis pour afficher un seul enregistrement tout en parcourant le jeu d'enregistrements.
Les résultats des tests ci-dessus seront utilisés pour comparer avec les résultats des tests suivants.
4. ADOVBS.inc doit-il être référencé par inclusion ?
ADOVBS.inc fourni par Microsoft contient 270 lignes de code qui définissent la plupart des constantes de propriété ADO. Notre exemple ne fait référence qu’à 2 constantes d’ADOVBS.inc. Par conséquent, dans ce test (ADO__02.asp), nous avons supprimé la référence de fichier incluse et utilisé directement la valeur correspondante lors de la définition des propriétés.
objRS.CursorType = 0 ?' adOpenForwardOnly
objRS.LockType = 1' adLockReadOnly
Vous pouvez constater que la surcharge de page a diminué de 23 %. Cette valeur n'affecte pas le temps de récupération et d'affichage des enregistrements individuels, puisque les modifications apportées ici n'affectent pas les opérations de jeu d'enregistrements au sein de la boucle. Il existe plusieurs façons de résoudre les problèmes de référence ADOVBS.inc. Nous vous recommandons d'utiliser le fichier ADOVBS.inc comme référence et d'expliquer les paramètres via des commentaires. N'oubliez pas, comme indiqué dans la première partie, qu'une utilisation modérée des commentaires a un impact minime sur l'efficacité de votre code. Une autre méthode consiste à copier les constantes dont vous avez besoin du fichier ADOVBS.inc dans la page.
Il existe également un bon moyen de résoudre ce problème, qui consiste à rendre toutes les constantes ADO directement disponibles en créant un lien vers la bibliothèque de types ADO. Ajoutez le code suivant au fichier Global.asa pour accéder directement à toutes les constantes ADO :
<!--METADATA TYPE=typelib
FILE=C:Fichiers de programmeFichiers communsSYSTEMADOmsado15.dll
NOM=Bibliothèque de types ADODB -->
ou:
<!--METADATA TYPE=typelib
UUID=00000205-0000-0010-8000-00AA006D2EA4
NOM=Bibliothèque de types ADODB -->
Par conséquent, notre première règle est la suivante :
lÉvitez d'inclure le fichier ADOVBS.inc et accédez et utilisez les constantes ADO via d'autres méthodes.
5. Dois-je créer un objet de connexion distinct lors de l'utilisation d'un jeu d'enregistrements ?
Pour répondre correctement à cette question, nous devons analyser le test dans deux conditions différentes : premièrement, la page n'a qu'une seule transaction de base de données ; deuxièmement, la page a plusieurs transactions de base de données ;
Dans l'exemple précédent, nous avons créé un objet Connection distinct et l'avons affecté à la propriété ActiveConnection du Recordset. Cependant, comme indiqué dans ADO__03.asp, nous pouvons également attribuer la chaîne de connexion directement à la propriété ActiveConnection, éliminant ainsi l'étape supplémentaire d'initialisation et de configuration de l'objet Connection dans le script.
objRS.ActiveConnection = Application (Conn)
Bien que l'objet Recordset doive encore créer une connexion, la création s'effectue à ce stade dans des conditions hautement optimisées. En conséquence, la surcharge de page a encore diminué de 23 % par rapport au test précédent et, comme prévu, la durée d'affichage d'un seul enregistrement n'a pas changé de manière substantielle.
Notre deuxième règle est donc la suivante :
lSi vous n'utilisez qu'un seul jeu d'enregistrements, attribuez directement la chaîne de connexion à la propriété ActiveConnection.
Nous vérifions ensuite si les règles ci-dessus sont toujours valides lorsque la page utilise plusieurs jeux d'enregistrements. Pour tester cette situation, nous introduisons une boucle FOR pour répéter 10 fois l’exemple précédent. Dans ce test, nous examinerons trois variantes :
Tout d’abord, comme indiqué dans ADO__04.asp, l’objet Connection est établi et détruit dans chaque boucle :
Copiez le code comme suit :
Faible je
Pour i = 1 à 10
Définir objConn = Server.CreateObject (ADODB.Connection)
objConn.Ouvrir l'application (Conn)
Définir objRS = Server.CreateObject (ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Application ouverte (SQL)
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire des titres
...
'écrire des données
...
Fin si
objRS.Fermer
Définir objRS = Rien
objConn.Fermer
Définir objConn = Rien
Suivant
Deuxièmement, comme indiqué dans ADO__05.asp, créez un objet Connection en dehors de la boucle et partagez cet objet avec tous les jeux d'enregistrements :
Copiez le code comme suit :
Définir objConn = Server.CreateObject (ADODB.Connection)
objConn.Ouvrir l'application (Conn)
Faible je
Pour i = 1 à 10
Définir objRS = Server.CreateObject (ADODB.Recordset)
objRS.ActiveConnection = objConn
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Application ouverte (SQL)
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire des titres
...
'écrire des données
...
Fin si
objRS.Fermer
Définir objRS = Rien
Suivant
objConn.Fermer
Définir objConn = Rien
Troisièmement, comme indiqué dans ADO__06.asp, attribuez la chaîne de connexion à la propriété ActiveConnection dans chaque boucle :
Copiez le code comme suit :
Faible je
Pour i = 1 à 10
Définir objRS = Server.CreateObject (ADODB.Recordset)
objRS.ActiveConnection = Application (Conn)
objRS.CursorType = 0 'adOpenForwardOnly
objRS.LockType = 1 'adLockReadOnly
objRS.Application ouverte (SQL)
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire des titres
...
'écrire des données
...
Fin si
objRS.Fermer
Définir objRS = Rien
Suivant
Comme nous pouvons le deviner, créer et supprimer des objets de connexion au sein d’une boucle est le moyen le moins efficace. Étonnamment, cependant, l'attribution de la chaîne de connexion directement à la propriété ActiveConnection dans la boucle n'est que légèrement plus lente que le partage d'un seul objet Connection.
Néanmoins, la troisième règle devrait être :
lLorsque plusieurs jeux d'enregistrements sont utilisés dans la même page, créez un seul objet de connexion et partagez-le via la propriété ActiveConnection.
6. Quel type de curseur et quelle méthode de verrouillage d'enregistrement sont les plus efficaces ?
Dans tous les tests jusqu'à présent, nous n'avons utilisé que des curseurs avant uniquement pour accéder au jeu d'enregistrements. Il existe trois types de curseurs fournis par ADO pour les jeux d'enregistrements : les curseurs à défilement statiques, les curseurs à défilement dynamiques et les curseurs de jeu de touches. Chaque curseur offre différentes fonctions, telles que l'accès à l'enregistrement précédent et à l'enregistrement suivant, la possibilité de voir les modifications apportées aux données par d'autres programmes, etc. Cependant, une discussion détaillée des fonctions de chaque type de curseur dépasse le cadre de cet article. Le tableau suivant est une analyse comparative de différents types de curseur.
Tous les autres types de curseurs nécessitent une surcharge supplémentaire par rapport aux curseurs avant uniquement, et ces curseurs sont généralement plus lents dans les boucles. Par conséquent, nous aimerions partager avec vous la mise en garde suivante : ne pensez jamais ainsi - eh bien, parfois j'utiliserai des curseurs dynamiques, donc j'utiliserai toujours ce curseur.
Le même sentiment s’applique au choix de la méthode de verrouillage des enregistrements. Le test précédent utilisait uniquement la méthode de verrouillage en lecture seule, mais il existe trois autres méthodes : traitement par lots conservateur, ouvert et ouvert. Comme les types de curseur, ces méthodes de verrouillage offrent des fonctionnalités et un contrôle différents sur l'utilisation des données de jeu d'enregistrements.
On arrive aux règles suivantes :
lUtilisez le type de curseur le plus simple et la méthode de verrouillage d'enregistrement adaptée à la tâche.
7. Quelle méthode est la meilleure à utiliser pour extraire un jeu d’enregistrements ?
Jusqu'à présent, nous avons extrait des jeux d'enregistrements en créant des objets Recordset, mais ADO fournit également des méthodes d'extraction indirectes de jeux d'enregistrements. Le test suivant compare ADO__03.asp et la création d'un jeu d'enregistrements directement à partir de l'objet Connection (CONN_01.asp) :
Copiez le code comme suit :
Définir objConn = Server.CreateObject (ADODB.Connection)
objConn.Ouvrir l'application (Conn)
Définir objRS = objConn.Execute(Application(SQL))
Vous pouvez voir que la surcharge de la page a légèrement augmenté et que la durée d'affichage d'un seul enregistrement n'a pas changé.
Jetons un coup d'œil à la création d'un objet recordset (CMD__02.asp) directement à partir de l'objet Command :
Copiez le code comme suit :
Définir objCmd = Server.CreateObject (ADODB.Command)
objCmd.ActiveConnection = Application (Conn)
objCmd.CommandText = Application (SQL)
Définir objRS = objCmd.Execute
De même, la surcharge de page augmente légèrement sans changement substantiel dans la durée d'affichage d'un seul enregistrement. La différence de performances entre les deux dernières méthodes est faible, mais nous devons prendre en compte un problème important.
Lors de la création d'un jeu d'enregistrements via la classe Recordset, nous pouvons contrôler le traitement du jeu d'enregistrements avec la plus grande flexibilité. Étant donné que les deux dernières méthodes ne parviennent pas à atteindre des performances écrasantes, nous considérons principalement le type de curseur et la méthode de verrouillage d'enregistrement renvoyés par défaut. Dans certaines occasions, la valeur par défaut n'est pas nécessairement la plus idéale.
Par conséquent, à moins qu’il n’y ait des raisons particulières de choisir entre ces deux dernières méthodes, nous recommandons de considérer les règles suivantes :
l Instanciez le jeu d'enregistrements via la classe ADODB.Recordset pour obtenir les meilleures performances et flexibilité.
8. Dois-je utiliser un jeu d'enregistrements local ?
ADO permet l'utilisation de jeux d'enregistrements locaux (clients). À ce stade, la requête extraira toutes les données du jeu d'enregistrements. Une fois la requête terminée, la connexion peut être fermée immédiatement et les curseurs locaux peuvent être utilisés pour accéder aux données. l'avenir, ce qui facilite la libération de la connexion. L'utilisation de jeux d'enregistrements locaux est importante pour accéder à des services de données distants qui nécessitent que les données soient utilisées hors ligne, mais sera-t-elle également utile pour les applications ordinaires ?
Ensuite, nous ajoutons l'attribut CursorLocation et fermons la connexion (CLIENT1.asp) après avoir ouvert le jeu d'enregistrements :
Copiez le code comme suit :
Définir objRS = Server.CreateObject (ADODB.Recordset)
objRS.CursorLocation = 2' adUseClient
objRS.ActiveConnection = Application (Conn)
objRS.LockType = 1 ? adLockReadOnly
objRS.Application ouverte (SQL)
objRS.ActiveConnection = Rien
En théorie, cette approche améliorerait l'efficacité pour deux raisons : premièrement, elle évite de demander des données à plusieurs reprises via la connexion lors du déplacement entre les enregistrements. Deuxièmement, elle allège les besoins en ressources ; Cependant, il semble d'après le tableau ci-dessus que l'utilisation d'un jeu d'enregistrements local ne contribuera évidemment pas à améliorer l'efficacité. Cela peut être dû au fait que lors de l'utilisation d'un jeu d'enregistrements local, le curseur devient toujours un type statique, quels que soient les paramètres du programme.
La règle 6 est la suivante :
lCela doit être évité à moins que la localisation du jeu d'enregistrements ne soit réellement requise.
10. Quelle méthode est la plus efficace à utiliser pour référencer les valeurs de champ dans un jeu d'enregistrements ?
10.1 Tests
Jusqu'à présent, nous avons fait référence aux valeurs de champ dans le jeu d'enregistrements par leur nom. Comme cette méthode nécessite de trouver à chaque fois le champ correspondant, elle n’est pas très efficace. Pour le démontrer, dans le test suivant, nous référençons la valeur d'un champ par son index dans la collection (ADO__08.asp) :
Copiez le code comme suit :
'écrire des données
Faire sans objRS.EOF
Réponse.Write(_
<TR> & _
<TD> & objRS(0) & </TD> & _
<TD> & objRS(1) & </TD> & _
<TD> & objRS(2) & </TD> & _
<TD> & objRS(3) & </TD> & _
<TD> & objRS(4) & </TD> & _
<TD> & objRS(5) & </TD> & _
<TD> & objRS(6) & </TD> & _
</TR> _
)
objRS.MoveNext
Boucle
Comme prévu, il y a également un petit changement dans la surcharge des pages (peut-être en raison d'une légère réduction du code). Cependant, l’amélioration du temps d’affichage avec cette approche est tout à fait perceptible.
Dans le test suivant, nous lions tous les champs aux variables individuellement (ADO__09.asp) :
Copiez le code comme suit :
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire des titres
...
Faible fld0
Dim fld1
Dim fld2
Faible fld3
Faible fld4
Dim fld5
Dim fld6
Définir fld0 = objRS(0)
Définir fld1 = objRS(1)
Définir fld2 = objRS(2)
Définir fld3 = objRS(3)
Définir fld4 = objRS(4)
Définir fld5 = objRS(5)
Définir fld6 = objRS(6)
'écrire des données
Faire sans objRS.EOF
Réponse.Write(_
<TR> & _
<TD> & fld0 & </TD> & _
<TD> & fld1 & </TD> & _
<TD> & fld2 & </TD> & _
<TD> & fld3 & </TD> & _
<TD> & fld4 & </TD> & _
<TD> & fld5 & </TD> & _
<TD> & fld6 & </TD> & _
</TR> _
)
objRS.MoveNext
Boucle
Définir fld0 = Rien
Définir fld1 = Rien
Définir fld2 = Rien
Définir fld3 = Rien
Définir fld4 = Rien
Définir fld5 = Rien
Définir fld6 = Rien
Réponse.Write(</TABLE>)
Fin si
C'est le meilleur disque jusqu'à présent. Veuillez noter que le temps d'affichage d'un seul enregistrement a été réduit à moins de 0,45 milliseconde.
Les scripts ci-dessus nécessitent tous une certaine compréhension de la construction du jeu d'enregistrements de résultats. Par exemple, nous utilisons les noms de champs directement dans les en-têtes de colonnes pour référencer chaque valeur de champ individuellement. Dans le test suivant, non seulement les données de champ sont obtenues en parcourant la collection de champs, mais les titres de champs sont également obtenus de la même manière. Il s'agit d'une solution plus dynamique (ADO__10.asp).
Copiez le code comme suit :
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
'écrire les en-têtes Response.Write(<TABLE BORDER=1><TR>)
Pour chaque objFld dans objRS.Fields
Réponse.Write(<TH> & objFld.name & </TH>)
Suivant
Réponse.Write(</TR>)
'écrire des données
Faire sans objRS.EOF
Réponse.Write(<TR>)
Pour chaque objFld dans objRS.Fields
? Réponse.Write(<TD> & objFld.value & </TD>)
Suivant
Réponse.Write(</TR>)
objRS.MoveNext
Boucle
Réponse.Write(</TABLE>)
Fin si
Comme vous pouvez le constater, les performances du code ont diminué, mais elles restent plus rapides que ADO__07.asp.
L'exemple de test suivant est un compromis des deux méthodes précédentes. Nous continuerons à maintenir la fonctionnalité dynamique tout en améliorant les performances en enregistrant les références de champs dans des tableaux alloués dynamiquement :
Copiez le code comme suit :
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
Autre
Dim fldCount
fldCount = objRS.Fields.Count
Dim fld()
ReDim fld(fldCount)
Faible je
Pour i = 0 à fldCount-1
Définir fld(i) = objRS(i)
Suivant
'écrire des titres
Response.Write(<TABLE BORDER=1><TR>) Pour i = 0 à fldCount-1
Réponse.Write(<TH> & fld(i).name & </TH>)
Suivant
Réponse.Write(</TR>)
'écrire des données
Faire sans objRS.EOF
Réponse.Write(<TR>)
Pour i = 0 à fldCount-1
Réponse.Write(<TD> & fld(i) & </TD>)
Suivant
Réponse.Write(</TR>)
objRS.MoveNext
Boucle
Pour i = 0 à fldCount-1
Définir fld(i) = Rien
Suivant
Réponse.Write(</TABLE>)
Fin si
Bien qu'il ne batte pas le meilleur précédent, il est plus rapide que les premiers exemples et présente l'avantage de traiter dynamiquement n'importe quel ensemble d'enregistrements.
Par rapport au code de test précédent, le code de test suivant a été fondamentalement modifié. Il utilise la méthode GetRows de l'objet Recordset pour remplir le tableau pour une itération sur les données, plutôt que d'accéder directement au Recordset lui-même. Notez que Recordset est défini sur Nothing immédiatement après l'appel de GetRows, ce qui signifie que les ressources système sont libérées dès que possible. Notez également que la première dimension du tableau représente les champs et la deuxième dimension représente les lignes (ADO__12.asp).
Copiez le code comme suit :
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
objRS.Fermer
Définir objRS = Rien
Autre
'écrire des titres
...
'définir le tableau
Faible arrRS
arrRS = objRS.GetRows
'fermer le jeu d'enregistrements plus tôt
objRS.Fermer
Définir objRS = Rien
'écrire des données
DimnumRangées
DimnumFlds
Ligne sombre
Dim.
numFlds = Ubound(arrRS, 1)
numRows = Ubound(arrRS, 2)
Pour ligne = 0 à numRows
Réponse.Write(<TR>)
Pour fld = 0 à numFlds
Réponse.Write(<TD> & arrRS(fld, ligne) & </TD>)
Suivant
Réponse.Write(</TR>)
Suivant
Réponse.Write(</TABLE>)
Fin si
Lors de l'utilisation de la méthode GetRows, l'intégralité du jeu d'enregistrements est extraite dans un tableau. Bien que des problèmes de ressources puissent survenir lorsque le jeu d'enregistrements est extrêmement volumineux, l'accès aux données dans une boucle est en effet plus rapide car les appels de fonctions tels que MoveNext et la vérification d'EOF sont annulés.
La vitesse a un coût, désormais les métadonnées du jeu d'enregistrements sont perdues. Pour résoudre ce problème, nous pouvons extraire les informations d'en-tête de l'objet recordset avant d'appeler GetRows. De plus, le type de données et d'autres informations peuvent également être extraites à l'avance ; Notez également que l'avantage en termes de performances lors des tests ne se produit que lorsque le jeu d'enregistrements est plus grand.
Dans le dernier test de cet ensemble, nous utilisons la méthode GetString du jeu d'enregistrements. La méthode GetString extrait l'intégralité du jeu d'enregistrements dans une grande chaîne et vous permet de spécifier le délimiteur (ADO__13.asp) :
Copiez le code comme suit :
Si objRS.EOF Alors
Response.Write (Aucun enregistrement trouvé)
objRS.Fermer
Définir objRS = Rien
Autre
'écrire des titres
...
'définir le tableau
Dim strTable
strTable = objRS.GetString (2, , </TD><TD>, </TD></TR><TR><TD>)
'fermer le jeu d'enregistrements plus tôt
objRS.Fermer
Définir objRS = Rien
Réponse.Write(strTable & </TD></TR></TABLE>)
Fin si