Tables internes :
Fonctionnement et optimisation des
performances
SOMMAIRE
INTRODUCTION 4
1. FONCTIONNEMENT D’UNE TABLE INTERNE 5
1.1 PRINCIPE DE BASE 5
1.2 OPTIMISATION EN DÉFINISSANT UNE TAILLE INITIALE 6
1.3 OPTIMISATION EN LIBÉRANT DE LA MÉMOIRE 7
2. INDEXATION 9
2.1 GÉNÉRALITÉS 9
2.2 INDEX LINÉAIRE 9
2.3 ARBRE BINAIRE ÉQUILIBRÉ 11
2.4 HACHAGE 13
3. TYPES DE TABLES INTERNES 14
3.1 TABLES D’INDEX 15
3.1.1 Tables standards 15
3.1.2 Tables triées 15
3.2 TABLES DE HACHAGE 15
4. OPÉRATIONS SUR LES TABLES INTERNES 16
4.1 INSERTION 16
4.1.1 Insertion entrée par entrée 16
4.1.2 Insertion par bloc d’entrées 17
4.2 LECTURE 18
4.2.1 Lecture entrée par entrée 18
4.2.2 Lecture d’une seule entrée 19
4.3 MODIFICATION 20
4.3.1 Position de l’entrée inconnue 20
4.3.2 Position de l’entrée connue 20
4.4 SUPPRESSION 21
Tables internes : Fonctionnement et optimisation des performances
3
CONCLUSION 22
TABLE DES ILLUSTRATIONS 23
Tables internes : Fonctionnement et optimisation des performances
4
Introduction
Cet ebook est destiné à toute personne s’intéressant de près comme de loin au code ABAP
dans l’ERP SAP. Il présente en détail le fonctionnement des tables internes qui sont des outils utilisés dans la majorité des programmes ABAP. Elles servent à manipuler les données lues dans la base de donées SAP, il est donc primordiale de connaître leur fonctionnement si l’on souhaite les utiliser le mieux possible.
Cet ouvrage vous apporte également des conseils sur les instructions à utiliser avec les tables internes. Pour chaque type de table interne, il vous présentera un récapitulatif des performances de l’opération que vous souhaitez faire sur ce type de table, suivant l’instruction que vous souhaitez employer.
En bref, après avoir lu ce livre serez un expert des tables internes. Je vous souhaite donc une bonne lecture et j’espère que vous trouverez réponse à toutes les questions que vous vous posiez sur les tables internes.
Tables internes : Fonctionnement et optimisation des performances
5
1. Fonctionnement d’une table interne
1.1 Principe de base
Lorsque vous tapez l’instruction :
DATA : lt_table TYPE TABLE OF ty_structure.
Le système créé seulement une référence en mémoire (8 octets). Ce n’est que lorsque vous insérerez une entrée dans la table que le système prendra la peine de créer l’en-tête de la table ainsi que son corps. Le corps d’une table interne est géré sous forme de pages. Chaque page contient des lignes et a une taille comprise entre 8Ko et 16Ko suivant la taille des lignes. En règle générale, les deux premières pages sont plus petites que 8Ko. Quant à l’en-tête (100 octets environ), il est composé de la référence de la première entrée de la première page du corps ainsi que de la référence du gestionnaire de page. Le gestionnaire de pages permet de gérer l’ensemble des adresses des pages (sauf la première) contenues dans la mémoire du système. Sa taille mémoire dépend du nombre de pages qui se trouvent dans le corps de la table. On peut le voir comme une table d’adresses. Voici une façon de schématiser une table interne de 4 pages en mémoire :
Figure 1 : Représentation d'une table interne de 4 pages en mémoire
Tables internes : Fonctionnement et optimisation des performances
6
1.2 Optimisation en définissant une taille initiale
Les très petites tables internes sont sources d’une perte de performance lorsque le système calcule la taille de la première page de leur corps. Pour éviter ce problème, il existe l’option INITIAL SIZE qui vous permet de déterminer vous-même la taille de la première page du corps de la table interne :
DATA : lt_table TYPE TABLE OF structure INITIAL SIZE n. Le fait de définir cette taille n’est pas bloquant si ensuite la table doit contenir plus d’entrée que ce que vous avez défini au départ. Cependant, il vaut mieux prendre le temps de bien la choisir car si elle est trop petite elle aura des effets plus néfastes sur les performances que si vous n’aviez pas précisé de taille. En effet, si vous décidez de déclarer une table de taille initiale 5 et que vous avez 7 entrées à insérer, alors vous aurez deux pages de 5 lignes allouées en mémoire. Pourtant, la deuxième page sera remplie avec seulement 2 entrées. Dans ce cas, une taille initiale de 8 aurait été plus profitable qu’une taille de 5 car vous auriez perdu moins d’emplacements mémoire. Voici une petite illustration de cet exemple :
Figure 2 : Comparaison entre deux tailles initiales de pages
Tables internes : Fonctionnement et optimisation des performances
7
1.3 Optimisation en libérant de la mémoire
Lorsque vous n’avez plus besoin du contenu d’une table, il est préférable pour les performances, de libérer l’espace mémoire alloué à ce contenu. Pour ce faire, il y a deux façons de procéder. La première consiste au vidage des pages. C’est la solution la plus adaptée si vous devez réutiliser la table plus tard dans votre programme. En effet, elle ne supprime pas les pages ni l’en-tête mais seulement leur contenu. De ce fait, le système n’aura pas à recréer des pages lorsque vous voudrez vous en resservir. Cette solution s’applique en utilisant les instructions REFRESH et CLEAR. Voici une illustration de ce que pourrais donner cette solution :
Figure 3 : Résultat après utilisation de REFRESH et CL EAR
Il ne faut pas confondre les instructions CLEAR et REFRESH avec l’instruction DELETE. Cette dernière permet de supprimer des lignes d’une table interne, mais elle ne permet en aucun cas de libérer l’espace mémoire qu’elles allouent. En effet, l’espace restera alloué, simplement ces lignes n’apparaîtront plus dans la table. Grossièrement, le DELETE peut s’illustrer comme ceci (voir les lignes barrées) :
Figure 4 : Le DELETE ne libère pas d'espace
Tables internes : Fonctionnement et optimisation des performances
8
La deuxième solution consiste à la libération de toute la mémoire allouée à la table. Elle implique la suppression de toutes les données qui sont liées à la table. Seul l’en-tête sera conservé par le système pour être réutilisé. Cette solution est préconisée lorsque vous n’avez plus à vous resservir de la table en question. Elle s’applique en utilisant l’instruction FREE. L’utilisation de cette instruction pourrait s’illustrer comme ceci :
Figure 5 : Ce qui reste après un FREE
Nous venons de voir comment libérer de la mémoire quand on a plus besoin de tout le contenu d’une table. Maintenant nous allons voir comment libérer de la mémoire lorsqu’une seule partie du contenu ne nous intéresse plus. Pour se faire, il est conseillé d’insérer ces lignes dans une deuxième table interne de même structure :
Figure 6 : Libérer les lignes qui ne servent plus e n utilisant une deuxième table
Une fois cette étape réalisée, vous pourrez alors utiliser l’instruction FREE pour libérer l’espace mémoire de la première table. Bien sûr, l’en-tête de la première table existera toujours une fois le FREE exécuté, mais l’espace qu’il prend est négligeable par rapport à l’espace pris par les entrées qui ne servent plus.
Nous parlions ici d’insertion et non de duplication. Le fait de recopier la table dans une autre ne changera rien. Par contre, en insérant simplement les lignes que vous voulez garder, vous vous assurez que rien d’autre ne sera conservé. Vous devez donc utiliser les instructions INSERT ou APPEND pour faire ce travail.
Tables internes : Fonctionnement et optimisation des performances
9
2. Indexation
Dans ce chapitre, nous verrons ce qu’est un index et nous parlerons en particulier de trois types d’indexation qui sont l’index linéaire, l’arbre binaire équilibré et le hachage. 2.1 Généralités
Un index est un outil permettant de trouver rapidement des informations dans une table. Pour se faire, il contient les références de chaque entrée d’une table, triées suivant la vision que l’on souhaite avoir de cette table. Par exemple, si nous avons une table gérant des livres et que nous souhaitons avoir une vue de ces livres triés par titre, nous aurons donc un index contenant des références triées selon l’ordre des titres. Il existe plusieurs types d’index qui sont plus ou moins efficaces suivant la situation dans laquelle ils sont employés. La façon dont ils trient les données diffère, mais le principe général reste le même pour tous : optimiser un accès à l’information selon des critères.
2.2 Index linéaire
Dans un programme ABAP, un index linéaire peut être vu comme une table à une colonne, contenant les références des entrées d’une table interne :
Figure 7 : Représentation d'un index linéaire en mé moire
Tables internes : Fonctionnement et optimisation des performances
10
Lorsqu’ une entrée est insérée dans une table interne, sa référence est insérée en respectant l’ordre de l’index. Prenons l’exemple d’une table interne non triée contenant une liste de livres :
Figure 8 : Exemple d'index linéaire
Je décide maintenant de trier ma table suivant le champ Année :
Figure 9 : Exemple d'index linéaire après tri
Comme vous le voyez, le contenu de ma table n’est pas perturbé, seul le contenu de l’index a changé. Ce principe est très intéressant puisqu’il ne remet pas en cause le fonctionnement assez complexe des pages (vu dans le chapitre précédent) tout en permettant d’accélérer le processus de recherche de données. Si je décide maintenant d’insérer un nouveau livre publié en 1999, par exemple :
Figure 10 : Exemple d'index linéaire après ajout
La référence a été ajoutée en deuxième position dans l’index. C’est ajout a donc nécessité le parcours de l’index de manière séquentielle (ligne par ligne), puis le décalage des références déjà présentes.
Tables internes : Fonctionnement et optimisation des performances
11
2.3 Arbre binaire équilibré
Un index linéaire est un très bon outil lorsqu’on manipule peu de données, mais pour des milliers de données, il n’est plus assez performant. En effet, comme nous venons de le voir, à chaque insertion ou suppression dans une table interne, un travail de tri très coûteux est réalisé. La solution pour rester performant est d’adopter une structure d’arbre binaire. Le principe de base est simple : lors de l’ajout d’une référence dans l’index, si sa priorité est inférieure, elle est insérée à gauche de la racine ou du nœud sinon elle est insérée à droite. En ABAP, la représentation d’un arbre binaire ressemble à ceci :
Figure 11 : Représentation d'un arbre binaire en mé moire
Tables internes : Fonctionnement et optimisation des performances
12
Avec notre exemple précédent de livres triés par année de parution on aurait cet index :
Figure 12 : Exemple d'arbre binaire
Si j’ajoute un nouveau livre écrit en 1997, on aura :
Figure 13 : Exemple d'arbre binaire après ajout
Comme vous pouvez le voir cet index est beaucoup plus performant que le précédent. Il n’y a plus besoin de décaler les références lors d’un ajout et on peut retrouver des données en parcourant beaucoup moins de lignes. Son seul défaut est qu’il peut vite est déséquilibré, c’est-à-dire qu’il peut avoir des branches beaucoup plus longues que d’autres ce qui influe négativement sur ses performances. Pour résoudre ce problème, des algorithmes dits d’équilibrage ont été créés. Je ne connais pas exactement celui qui est utilisé en ABAP mais, peu importe son fonctionnement, le résultat cherché est toujours le même : équilibré l’arbre, c’est-à-dire obtenir un arbre qui tend à avoir, autant que faire se peut, des branches de même longueur. Avec des branches de même longueur, l’arbre est bien plus performant car il y a moins de profondeur à analyser lors d’un traitement tel qu’une insertion ou une suppression ou encore une recherche de données.
Tables internes : Fonctionnement et optimisation des performances
13
2.4 Hachage
Le hachage consiste à transformer la clé d’une entrée en valeur numérique, dite valeur de hachage, en utilisant une fonction de hachage. La valeur de hachage détermine la position de l’entrée dans la table.
Figure 14 : Représentation du hachage en mémoire
L’avantage d’une telle méthode est que le temps d’accès aux données ne varie pas en fonction du nombre d’entrées de la table. En effet, pour retrouver les informations liées à une clé, on utilise la fonction de hachage et l’on connait instantanément l’endroit où est stockée l’entrée.
En reprenant l’exemple de la table interne qui contient des livres, on peut imaginer cette représentation :
Figure 15 : Exemple de hachage
Tables internes : Fonctionnement et optimisation des performances
14
3. Types de tables internes
Dans ce chapitre, nous allons nous intéresser aux spécificités de chaque type de table interne de l’ABAP. Il en existe trois au total : les tables standards, les tables triées et les tables de hachage. Voici un diagramme (assez célèbre) expliquant clairement les liens d’héritage qui lient ces trois types de table :
Figure 16 : Hiérarchie des types de tables
Le point commun entre le type de tables standard et le type de tables triées réside dans la gestion de leur index. C’est pourquoi ils héritent tous les deux de la classe des tables d’index. En ce qui concerne le type de tables de hachage, comme son nom l’indique, il est géré via un index de hachage qui n’a rien à voir avec l’index utilisé dans les autres types. C’est la raison pour laquelle il hérite directement du type de table le plus générique.
Tables internes : Fonctionnement et optimisation des performances
15
3.1 Tables d’index
3.1.1 Tables standards
Elles ont un index linéaire interne. Elles sont accessibles par index ou par clé, cependant le temps d’accès par clé est proportionnel au nombre d’entrées dans la table. De plus, les clés sont toujours non-uniques. Le type standard est le plus approprié si vous souhaitez accéder aux données d’une table en utilisant des index. Il peut s’avérer très utile aussi si vous souhaitez accéder aux données d’une table via la clé, à condition d’avoir trié la table après l’avoir remplie. Avec l’option « binary search » et en indiquant la clé, le temps de réponse sera alors le même que pour une table de type triée.
3.1.2 Tables triées
Elles sont triées par clé. Comme pour les tables standards, elles ont un index interne. Elles sont accessibles par index ou par clé mais peuvent bénéficier de clés uniques ou non-uniques contrairement aux tables standard. Pour un accès par clé et en utilisant l’option « binary search », le temps de réponse dépend du logarithme du nombre d’entrées dans la table. Les entrées sont insérées selon l’ordre de tri défini grâce à la clé de table. Le type trié est le plus approprié si vous souhaitez que la table soit triée au fur et à mesure de son remplissage. 3.2 Tables de hachage
Elles n’ont pas d’index. Elles sont accessibles seulement par clé. Le temps de réponse ne dépend pas du nombre d’entrées dans la table, il est constant. Évidemment elles exigent uniquement des clés uniques, ce qui peut ralentir l’insertion. Le type hachage est le plus approprié si vous souhaitez construire une table et l’utiliser de la même façon qu’une table du dictionnaire de données ou traiter une grande quantité de données.
Tables internes : Fonctionnement et optimisation des performances
16
4. Opérations sur les tables internes
Dans ce chapitre, vous trouverez quelques tableaux comparants les temps d’exécution de certaines instructions selon les tables sur lesquelles elles sont utilisées. Avant de commencer, voici un petit mémo mathématique :
- O(1) signifie que le temps est constant. - O(n) signifie que le temps est fonction linéaire du nombre n d’entrées dans la table. - O(log n) signifie que le temps est fonction logarithmique du nombre n d’entrées dans la
table. 4.1 Insertion
Il y a deux façons d’insérer des entrées dans une table internes, soit une par une, soit par bloc lorsque les entrées en question sont déjà dans une autre table interne. Lorsque les deux méthodes s’offrent à vous, préférez la seconde car la gestion mémoire sera réalisée par le système et donc sera plus optimisé que si vous insérez vous-même chaque ligne via une boucle.
4.1.1 Insertion entrée par entrée
L’insertion entrée par entrée est possible via ces trois instructions : - APPEND [wa TO|INITIAL LINE TO] itab. - INSERT [wa INTO|INITIAL LINE INTO] itab [INDEX idx]. - INSERT [wa INTO|INITIAL LINE INTO] TABLE itab.
Voici un petit tableau qui compare les temps d’exécution des instructions en fonction des tables sur lesquelles elles sont appliquées : Table standard Table triée Table de
hachage APPEND O(1) O(1) Impossible INSERT ... INTO ... INDEX
Si index linéaire O(n)
Si index en arbre O(log n)
Si index linéaire O(n)
Si index en arbre O(log n)
Impossible
INSERT ... INTO TABLE
O(1) O(log n) O(1)
Figure 17 : Comparaison des temps d'exécution d'une insertion entrée par entrée
L’insertion est toujours plus rapide lorsqu’elle est faite sur une table interne de type standard car aucune opération autre que l’insertion n’est réalisée, l’entrée est juste ajoutée en bas de la table interne. C’est le cas notamment de l’instruction APPEND qui semble avoir un temps d’exécution constant sur les tables internes standard ou triées. Le temps est certes constant mais un peu plus élevé lorsque l’on travaille sur une table interne triée.
Tables internes : Fonctionnement et optimisation des performances
17
4.1.2 Insertion par bloc d’entrées
L’ABAP offre deux instructions permettant d’insérer des entrées par bloc dans une table interne :
- APPEND LINES OF itab1 [FROM idx1] [TO idx2] TO itab2. - INSERT LINES OF itab1 [FROM idx1] [TO idx2] INTO TABLE itab2.
Selon le type de table sur lequel vous travaillez, vous serez plus ou moins contraint de choisir l’une ou l’autre de ces instructions. Par exemple, l’instruction APPEND LINES ne fonctionne pas avec les tables de hachage. L’APPEND LINES est plus rapide à l’exécution que l’INSERT LINES, mais ce n’est pas sans raison. En effet, l’INSERT LINES va travailler pour que le tri soit respecté quand le travail se fait sur une table triée alors que l’APPEND LINES non. Ce sera à vous de vous en assurez. D’une manière générale, il est donc plus prudent de réserver l’instruction APPEND LINES seulement aux tables de type standard. A noter que vous pouvez aussi utiliser les instructions MOVE et = pour insérer les entrées d’une table interne vers une autre. Je vous conseille quand même de ne pas trop les utiliser car elles sont moins efficaces que les précédentes.
Tables internes : Fonctionnement et optimisation des performances
18
4.2 Lecture
4.2.1 Lecture entrée par entrée
Dès que vous avez besoin de lire plusieurs lignes dans une table interne, vous n’avez d’autre choix que de boucler sur cette table interne. A partir de là, suivant le type de table sur lequel vous travaillez et la façon dont vous souhaitez boucler (avec clé, sans clé, …) vous serez obligé de parcourir toute la table ou seulement une partie. Voici un tableau qui compare les temps d’exécution des principales variantes de l’instruction LOOP en fonction des tables sur lesquelles elles sont appliquées : Table standard Table triée Table de
hachage LOOP...WHERE ENDLOOP (avec une clé complète)
O(n) (Toute la table est passée en revue)
O(log n) O(1)
LOOP...WHERE ENDLOOP (avec la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(log n) O(n) (Toute la table est passée en revue)
LOOP...WHERE ENDLOOP (Sans la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
LOOP...FROM ... TO ENDLOOP
O(1) O(1) Impossible
LOOP ENDLOOP
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
Figure 18 : Comparaison des temps d'exécution d'une lecture entrée par entrée
Lorsque vous utilisez l’instruction LOOP, vous disposez de plusieurs façons de traiter l’entrée en cours. Soit vous copiez cette entrée dans une zone de travail avec l’option INTO, ce qui n’est pas très optimisé car vous effectuez une copie pour chaque ligne. Soit vous travaillez directement sur l’entrée en assignant l’adresse mémoire de l’entrée à un field symbol avec l’option ASSIGNING, c’est une bonne solution puisque vous ne copiez pas l’entrée. Soit, pour finir, vous travaillez avec l’adresse mémoire et vous la copiez dans une variable avec l’option REFERENCE INTO, ce qui est aussi bien que la solution précédente car l’entrée n’est pas copiée non plus. Personnellement, je préfère utiliser le field symbol mais c’est une question d’habitude. Ces deux dernières options peuvent vous permettre de réduire de moitié le temps d’exécution de la boucle sur laquelle elles sont ajoutées. Ne les négligez donc pas. Sachez, néanmoins, que si la table interne sur laquelle vous travaillez dispose de moins de 5 entrées de taille inférieure à 5000 octets, il est préférable que vous vous serviez de l’option INTO. En effet, la gestion du field symbol ou de la variable contenant les références serait plus consommatrice de mémoire que le traitement de copie en lui-même.
Tables internes : Fonctionnement et optimisation des performances
19
4.2.2 Lecture d’une seule entrée
La lecture d’une entrée d’une table interne se fait avec l’instruction READ. Comme pour l’instruction LOOP, vous pouvez placer l’entrée retournée par l’instruction READ dans une zone de travail via l’option INTO ou alors vous pouvez travailler avec un field symbol ou une variable de référence. Comme pour le LOOP, dans la mesure du possible, optez pour autre chose que l’option INTO… Voici un tableau qui compare les temps d’exécution des principales variantes de l’instruction READ en fonction des tables sur lesquelles elles sont appliquées : Table standard Table triée Table de
hachage READ...WITH KEY... (avec une clé complète)
O(n) (Toute la table est passée en revue)
O(log n) O(1)
READ...WITH KEY... (avec la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(log n) O(n) (Toute la table est passée en revue)
READ...WITH KEY... (Sans la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
READ ... INDEX
O(1) O(1) Impossible
Figure 19 : Comparaison des temps d'exécution de la lecture d'une seule entrée
L’ajout de l’option WITH TABLE KEY plutôt que l’option WITH KEY n’a aucun impact sur les performances. Tout dépend de la complétude de la clé. En revanche, l’utilisation de l’option BINARY SEARCH sur une table interne de type standard ou trié permet de passer d’un temps O(n) à un temps O(log n). Par contre, faites attention à ce que la table soit déjà triée sur le ou les champs sur lesquels la lecture est faite. De plus, utilisez cette option avec parcimonie car trier la table demande beaucoup de temps et ce temps n’est pas toujours récupéré via le BINARY SEARCH. Il est donc possible que cela vous fasse perdre plus de temps que ce que vous espérez gagner. Enfin, si vous souhaitez juste vérifier l’existence d’une entrée dans une table interne, c'est-à-dire ne pas vous servir de cette entrée pour faire un traitement, alors pensez à l’option TRANSPORTING NO FIELDS. Elle vous fera économiser le coût nécessaire à une copie, ce qui n’est pas négligeable quand la lecture se fait à l’intérieur d’une boucle. Avec cette option, vous n’aurez plus à préciser comment traiter l’entrée obtenue puisqu’elle ne sera pas retournée.
Tables internes : Fonctionnement et optimisation des performances
20
4.3 Modification
4.3.1 Position de l’entrée inconnue
La modification d’une entrée est une opération complexe pour le système lorsque vous ne savez pas où elle se trouve dans la table. Elle nécessite d’abord la recherche de l’entrée à modifier puis sa modification. Les temps d’exécution s’apparentent donc souvent à ceux d’une opération de lecture. La modification d’une entrée dans une table triée ou dans une table de hachage est possible que si vous ne touchez pas à la clé de l’entrée. Si vous devez modifier des champs appartenant à la clé, vous serez dans l’obligation d’utiliser une table de type standard. Voici un tableau qui compare les temps d’exécution des principales variantes de l’instruction MODIFY en fonction des tables sur lesquelles elles sont appliquées : Table standard Table triée Table de
hachage MODIFY ... TRANSPORTING ...WHERE (avec une clé complète)
O(n) (Toute la table est passée en revue)
O(log n) O(1)
MODIFY ... TRANSPORTING ...WHERE (avec la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(log n) O(n) (Toute la table est passée en revue)
MODIFY ... TRANSPORTING ...WHERE (Sans la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
MODIFY TABLE FROM structure
O(n) (Toute la table est passée en revue)
O(log n) O(1)
Figure 20 : Comparaison des temps d'exécution de la modification d’une entrée
4.3.2 Position de l’entrée connue
Ce cas de figure peut se produire lorsque vous connaissez la position (l’index) de l’entrée à modifier, à condition que la table dans laquelle elle se trouve ne soit pas une table de hachage, ou lorsque vous vous trouvez dans une boucle de type LOOP. Dans le premier cas, vous pourrez utiliser l’instruction MODIFY pour modifier l’entrée et bénéficier dans temps d’exécution constant :
MODIFY ... INDEX n FROM structure Dans le second cas, tout dépend de la façon dont vous traitez l’entrée en cours. Si vous utilisez l’option INTO, ce que je n’espère pas, vous devrez alors vous servir de l’instruction MODIFY citée dans le premier cas. Si vous avez eu le bon réflexe d’utiliser un field symbol ou une variable de
Tables internes : Fonctionnement et optimisation des performances
21
référence, alors vous pourrez modifier l’entrée juste en utilisant une affectation basique comme un MOVE ou un =. 4.4 Suppression
Le coût en temps d’une suppression est très semblable à celui d’une modification. Comme pour la modification, si on ne connait pas la position de l’entrée, il faut d’abord fournir un travail de recherche avant de la supprimer. Voici un tableau qui compare les temps d’exécution des principales variantes de l’instruction DELETE en fonction des tables sur lesquelles elles sont appliquées : Table standard Table triée Table de
hachage DELETE ... FROM ... TO
O(1) O(1) Impossible
DELETE ...WHERE (avec une clé complète)
O(n) (Toute la table est passée en revue)
O(log n) O(1)
DELETE ...WHERE (avec la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(log n) O(n) (Toute la table est passée en revue)
DELETE ...WHERE (Sans la première partie de la clé)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
O(n) (Toute la table est passée en revue)
DELETE ... INDEX
O(1) O(1) Impossible
DELETE FROM structure
O(n) (Toute la table est passée en revue)
O(log n) O(1)
DELETE TABLE WITH TABLE KEY
O(n) (Toute la table est passée en revue)
O(log n) O(1)
Figure 21 : Comparaison des temps d'exécution d'une suppression
Tables internes : Fonctionnement et optimisation des performances
22
Conclusion
Vous êtes maintenant un expert des tables internes. Vous savez comment elles fonctionnent et comment les utiliser au mieux. Vous pourrez vous servir de ce document à chaque fois que vous aurez à utiliser des tables internes. De cette manière, vous serez facilement guidé sur le type de table à utiliser ainsi que sur les instructions à coder.
Si des questions sur les tables internes restent sans réponse à la suite de la lecture de ce document, n’hésitez pas à écrire à l’auteur en passant par le formulaire de contact du site http://www.sapdecouverte.fr. Il se fera un plaisir de vous répondre.
Bonne continuation dans le monde SAP.
Tables internes : Fonctionnement et optimisation des performances
23
TABLE DES ILLUSTRATIONS
Figure 1 : Représentation d'une table interne de 4 pages en mémoire.............................................. 5
Figure 2 : Comparaison entre deux tailles initiales de pages............................................................. 6
Figure 3 : Résultat après utilisation de REFRESH et CLEAR............................................................ 7
Figure 4 : Le DELETE ne libère pas d'espace ................................................................................... 7
Figure 5 : Ce qui reste après un FREE ............................................................................................. 8
Figure 6 : Libérer les lignes qui ne servent plus en utilisant une deuxième table............................... 8
Figure 7 : Représentation d'un index linéaire en mémoire ................................................................. 9
Figure 8 : Exemple d'index linéaire ................................................................................................. 10
Figure 9 : Exemple d'index linéaire après tri.................................................................................... 10
Figure 10 : Exemple d'index linéaire après ajout ............................................................................. 10
Figure 11 : Représentation d'un arbre binaire en mémoire .............................................................. 11
Figure 12 : Exemple d'arbre binaire ................................................................................................ 12
Figure 13 : Exemple d'arbre binaire après ajout .............................................................................. 12
Figure 14 : Représentation du hachage en mémoire ...................................................................... 13
Figure 15 : Exemple de hachage .................................................................................................... 13
Figure 16 : Hiérarchie des types de tables ...................................................................................... 14
Figure 17 : Comparaison des temps d'exécution d'une insertion entrée par entrée ......................... 16
Figure 18 : Comparaison des temps d'exécution d'une lecture entrée par entrée ........................... 18
Figure 19 : Comparaison des temps d'exécution de la lecture d'une seule entrée .......................... 19
Figure 20 : Comparaison des temps d'exécution de la modification d’une entrée ........................... 20
Figure 21 : Comparaison des temps d'exécution d'une suppression ............................................... 21