Access
 sql >> Base de données >  >> RDS >> Access

Comment Access communique-t-il avec les sources de données ODBC ? Partie 2

MISE À JOUR : Ajout de quelques clarifications supplémentaires sur la signification de SQLExecute et comment Access gère les requêtes préparées. Merci Bob !

Que fait Access lorsque nous parcourons et examinons des enregistrements dans une table liée ODBC ?

Dans la deuxième partie de notre série de traçage ODBC, nous nous concentrerons sur l'impact des types de jeu d'enregistrements dans une table liée ODBC. Dans le dernier article, nous avons appris comment activer la trace SQL ODBC et nous pouvons maintenant voir la sortie. Si vous avez joué un peu avec, vous avez peut-être remarqué que votre requête Access et les instructions SQL ODBC générées par Access ne se ressemblent pas beaucoup. Nous fournirons également un aperçu approfondi de la manière dont les types influencent le comportement des requêtes SELECT, et nous examinerons également différentes variantes de jeux d'enregistrements tels que les instantanés et les Dynasets.

Si vous souhaitez suivre, vous pouvez utiliser l'exemple de base de données fourni ici.

Effet des types Recordset dans une requête SELECT

Les types de jeu d'enregistrements ont un effet important sur la manière dont Access communiquera avec les sources de données ODBC. Vous avez peut-être remarqué qu'en mode création de formulaire ou en mode création de requête, vous pouvez définir le type de jeu d'enregistrements. Par défaut, il est défini sur Dynaset .

En VBA, nous avons quelques options supplémentaires, mais nous ne nous en préoccuperons pas pour le moment. Commençons par comprendre ce qu'est exactement Dynaset et Snapshot signifie d'abord. Nous commencerons par le type moins couramment utilisé, Snapshot d'abord.

Jeux d'enregistrements de type instantané

Snapshot est assez simple. Cela signifie essentiellement que nous prenons un instantané du résultat au moment de l'exécution de la requête. Normalement, cela signifie également qu'Access ne peut pas mettre à jour le résultat. Cependant, regardons comment Access interroge la source avec un jeu d'enregistrements basé sur un instantané. Nous pouvons créer une nouvelle requête Access comme suit :

Le SQL tel que nous pouvons le voir dans la vue SQL de la requête Access est :

SELECT Cities.*
FROM Cities;
Nous allons exécuter la requête, puis examiner le sqlout.txt dossier. Voici le résultat, formaté pour plus de lisibilité :

SQLExecDirect:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
Il y avait peu de différences entre ce que nous avons écrit dans la requête d'Access et ce qu'Access a envoyé à ODBC, que nous analyserons.

  1. Access a qualifié la table avec le nom du schéma. Évidemment, dans le dialecte Access SQL, cela ne fonctionne pas de la même manière, mais pour le dialecte ODBC SQL, il est utile de s'assurer que nous sélectionnons dans la bonne table. Qui est régi par le SourceTableName propriété.
  2. Access a développé le contenu de Cities.* dans une liste énumérée de toutes les colonnes qu'Access connaît déjà sur la base des Fields collection du TableDef sous-jacent objet.
  3. L'accès a utilisé le " pour citer les identificateurs, ce à quoi le dialecte SQL ODBC s'attend. Même si Access SQL et Transact-SQL utilisent des crochets pour citer un identifiant, ce n'est pas une syntaxe légale dans le dialecte ODBC SQL.

Ainsi, même si nous n'avons fait qu'une simple requête d'instantané en sélectionnant toutes les colonnes d'une table, vous pouvez voir qu'Access effectue beaucoup de transformations sur le SQL entre ce que vous mettez dans la vue de conception de requête Access ou la vue SQL par rapport à ce qu'Access émet réellement aux données la source. Dans ce cas, cependant, il s'agit principalement de syntaxe, il n'y a donc pas de réelle différence dans l'instruction SQL entre la requête Access d'origine et l'instruction SQL ODBC.

La trace a également ajouté SQLExecDirect au début de l'instruction SQL. Nous y reviendrons une fois que nous aurons examiné quelques autres exemples.

Jeux d'enregistrements de type Dynaset

Nous allons utiliser la même requête mais redéfinir la propriété sur sa valeur par défaut, Dynaset .
Exécutez-le à nouveau, et nous verrons ce que nous obtenons du sqlout.txt . Encore une fois, il est formaté pour la lisibilité :

SQLExecDirect:
SELECT
  "Application"."Cities"."CityID"
FROM "Application"."Cities"

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?

SQLExecute: (GOTO BOOKMARK)

SQLPrepare:
SELECT
   "CityID"
  ,"CityName"
  ,"StateProvinceID"
  ,"Location"
  ,"LatestRecordedPopulation"
  ,"LastEditedBy"
  ,"ValidFrom"
  ,"ValidTo"
FROM "Application"."Cities"
WHERE "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?
   OR "CityID" = ?

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Wow, il se passe plein de choses ! C'est certainement plus bavard que le jeu d'enregistrements de type instantané. Passons-les en revue un par un.

Le premier ne sélectionne que le CityID colonne. Il se trouve que c'est la clé primaire de la table, mais plus important encore, c'est l'index qu'Access utilise de son côté. Cela deviendra important lorsque nous étudierons les vues plus tard. Access utilise cette requête pour obtenir les clés et l'utiliser pour remplir d'autres requêtes plus tard, comme nous le verrons.

La deuxième instruction est plus proche de la requête d'instantané d'origine, sauf que nous avons maintenant un nouveau WHERE filtrage de clause sur le CityID colonne. À partir de là, nous pouvons voir qu'il s'agit d'une récupération sur une seule ligne. Nous pouvons utiliser les clés que nous avons obtenues de la première requête et collecter le reste des colonnes dans cette requête. Chaque fois que cette instruction préparée est exécutée, vous verrez un SQLExecute: (GOTO BOOKMARK) .

Mais ce serait inefficace si nous devions le faire pour toutes les lignes… Et c'est là qu'intervient la requête suivante. La 3ème instruction est similaire à la 2ème mais a 10 prédicats. Cette requête préparée est exécutée avec chaque SQLExecute: (MULTI_ROW FETCH) . Donc, cela signifie que lorsque nous chargeons un formulaire ou une feuille de données ou même ouvrons un jeu d'enregistrements dans le code VBA, Access utilisera soit la version à une seule ligne, soit la version à plusieurs lignes et remplira les paramètres à l'aide des clés qu'il a obtenues du premier requête.

Récupération et resynchronisation en arrière-plan

Incidemment, avez-vous déjà remarqué que lorsque vous ouvrez un formulaire ou une feuille de données, vous ne voyez pas le "X de Y" dans la barre de navigation ?

C'est parce qu'Access ne peut pas savoir combien il y en a tant qu'il n'a pas fini de collecter les résultats de la première requête. C'est pourquoi vous constaterez souvent qu'il est très rapide d'ouvrir une requête qui renvoie une grande quantité de données. Vous ne prévisualisez qu'une petite fenêtre de l'ensemble du jeu d'enregistrements pendant qu'Access récupère les lignes en arrière-plan. Si vous cliquez sur le bouton "Aller au dernier", vous constaterez peut-être qu'il bloque l'accès. Vous devrez attendre qu'il ait fini de récupérer toutes les clés de la première requête avant que nous puissions voir le "X de Y" dans la barre de navigation.

Ainsi, vous pouvez apprécier comment Access peut donner l'illusion d'être rapide à ouvrir même un jeu d'enregistrements volumineux lorsque nous utilisons un jeu d'enregistrements de type dynaset et c'est généralement une bonne expérience pour l'utilisateur.

Enfin, nous devons noter que nous avons 3 types d'exécutions différents, SQLExecDirect , SQLPrepare et SQLExecute . Vous pouvez voir qu'avec le premier, nous n'avons aucun paramètre. La requête est simplement telle quelle. Cependant, si une requête doit être paramétrée, elle doit d'abord être préparée via SQLPrepare puis exécuté plus tard avec SQLExecute avec les valeurs des paramètres fournis. Nous ne pouvons pas voir quelles valeurs ont été réellement passées dans le SQLExecute déclaration bien que nous puissions déduire de ce que nous voyons dans Access. Vous pouvez seulement savoir s'il a récupéré une seule ligne (en utilisant SQLExecute: (GOTO BOOKMARK) ou plusieurs lignes (en utilisant SQLExecute: (MULTI-ROW FETCH) ). Access utilisera la version à plusieurs lignes pour effectuer une récupération en arrière-plan et remplir le jeu d'enregistrements de manière incrémentielle, mais utilisera la version à une seule ligne pour ne remplir qu'une seule ligne. Cela peut être le cas sur une vue de formulaire unique par opposition à une vue continue de formulaire ou de feuille de données ou l'utiliser pour la resynchronisation après une mise à jour.

Naviguer

Avec un jeu d'enregistrements suffisamment volumineux, Access peut ne pas être en mesure de terminer la récupération de tous les enregistrements. Comme indiqué précédemment, l'utilisateur reçoit les données dès que possible. Normalement, lorsque l'utilisateur navigue vers l'avant dans le jeu d'enregistrements, Access continue à récupérer de plus en plus d'enregistrements pour garder la mémoire tampon devant l'utilisateur.

Mais supposons que l'utilisateur passe à la 100e ligne en accédant au contrôle de navigation et en y saisissant 100 ?

Dans ce cas, Access soumettra les requêtes suivantes…

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (GOTO BOOKMARK)

SQLExecute: (MULTI-ROW FETCH)

SQLExecute: (MULTI-ROW FETCH)
Notez comment Access utilise les instructions déjà préparées qu'il a créées au moment de l'ouverture du jeu d'enregistrements. Parce qu'il a déjà les clés de la première requête, il est capable de savoir quelle est la "100e" ligne. Pour utiliser un exemple plus concret. Supposons que nous ayons CityID commençant à 1, 3, 4, 5…99, 100, 101, 102 sans enregistrement pour le CityID = 2 . Dans la première requête, le CityID 101 serait au 100e rang. Par conséquent, lorsque l'utilisateur saute à 100, Access recherche la 100e ligne dans la première requête, voir qu'il s'agit de CityID 101, puis prend cette valeur et l'introduit dans le SQLExecute: (GOTO BOOKMARK) pour accéder immédiatement à cet enregistrement. Il examine ensuite les 10 enregistrements suivants et utilise les CityID suivants pour remplir le tampon avec plusieurs SQLExecute: (MULTI-ROW FETCH) . Vous avez peut-être remarqué qu'il y a une extraction de plusieurs lignes avant une extraction d'une seule ligne. Access récupère en fait les lignes 101e à 110e dans la récupération de plusieurs lignes et récupère le 100e enregistrement dans la récupération de ligne unique suivante.

Une fois qu'Access a obtenu les données pour les lignes à la 100e ligne, il y emmène l'utilisateur, puis commence à remplir le tampon autour de cette 100e ligne. Cela permet à l'utilisateur d'afficher la 100e ligne sans avoir à attendre pour charger tous les 11e à 99e enregistrements. L'utilisateur a également une expérience de navigation apparemment rapide lorsqu'il clique sur précédent ou suivant à partir de la nouvelle position, car Access l'a déjà chargé en arrière-plan avant que l'utilisateur ne le demande. Cela aide à donner l'illusion d'être rapide même sur un réseau lent.

Mais même si l'utilisateur laissait le formulaire ouvert et inactif, Access continuerait à effectuer à la fois une récupération en arrière-plan et à actualiser la mémoire tampon pour éviter d'afficher les données obsolètes de l'utilisateur. Cela est régi par les paramètres ODBC dans la boîte de dialogue Options, sous la section Avancé de l'onglet Paramètres client :

L'intervalle d'actualisation ODBC par défaut est de 1 500 secondes, mais peut être modifié. Il peut également être modifié via VBA.

Conclusions :volumineuses ou bavardes

Vous devriez maintenant voir que la principale raison pour laquelle les jeux d'enregistrements de type dynaset sont modifiables, mais pas les jeux d'enregistrements de type instantané, est qu'Access est capable de remplacer une ligne dans le jeu d'enregistrements par la version la plus récente du même depuis le serveur car il sait comment sélectionner un seule rangée. Pour cette raison, Access doit gérer 2 requêtes ODBC; l'un pour récupérer les clés et l'autre pour récupérer le contenu réel des lignes pour une clé donnée. Cette information n'était pas présente avec un jeu d'enregistrements de type instantané. Nous venons de recevoir une grosse masse de données.

Nous avons examiné 2 principaux types de jeux d'enregistrements bien qu'il y en ait plus. Cependant, d'autres ne sont que des variantes des 2 types que nous avons couverts. Mais pour l'instant, il suffit de rappeler qu'utiliser snapshot, c'est être volumineux dans notre communication réseau. D'un autre côté, utiliser dynaset signifie que nous serons bavards. Les deux ont leurs hauts et leurs bas.

Par exemple, le jeu d'enregistrements d'instantané n'a plus besoin de communiquer avec le serveur une fois qu'il a récupéré les données. Tant que le jeu d'enregistrements reste ouvert, Access peut naviguer librement dans son cache local. L'accès n'a pas non plus besoin de conserver de verrous et donc de bloquer les autres utilisateurs. Cependant, un jeu d'enregistrements d'instantané est par nécessité plus lent à s'ouvrir car il doit collecter toutes les données à l'avance. Cela peut ne pas convenir à un jeu d'enregistrements volumineux, même si vous avez l'intention de lire toutes les données.

Supposons que vous créez un grand rapport Access de 100 pages, il est généralement intéressant d'utiliser un jeu d'enregistrements de type dynaset. Il peut commencer à rendre l'aperçu dès qu'il en a assez pour rendre la première page. C'est mieux que de vous forcer à attendre qu'il ait récupéré toutes les données avant de pouvoir commencer à rendre l'aperçu. Bien qu'un jeu d'enregistrements de feuille de réponse dynamique puisse prendre des verrous, c'est généralement pour une courte durée. Il est juste assez long pour qu'Access resynchronise son cache local.

Mais quand on pense au nombre de requêtes supplémentaires qu'Access soumet sur le réseau avec un jeu d'enregistrements de type dynaset, il est facile de voir que si la latence du réseau est faible, les performances d'Access en souffriront en conséquence. Pour qu'Access permette aux utilisateurs de modifier et de mettre à jour les sources de données de manière générique, il faut qu'Access garde une trace des clés pour sélectionner et modifier une seule ligne. Nous verrons cela dans les prochains articles. Dans le prochain article, nous verrons comment le tri et les groupes affectent un jeu d'enregistrements de type dynaset ainsi que comment Access détermine la clé à utiliser pour un jeu d'enregistrements de type dynaset.

Pour plus d'aide avec Microsoft Access, appelez nos experts au 773-809-5456 ou envoyez-nous un e-mail à [email protected].