Stockage des données - Sybase ASE 12.5.2


1- Introduction

Cette documentation se propose de présenter à travers des cas pratiques le stockage sous Sybase Adaptive Server Enterprise 12.5.2.

Outre les aspects théoriques, à travers cette documentation, les points ci-dessous seront évoqués :

2- Pages Adaptiver Server

L'unité de stockage élémentaire pour Adaptive Server est la page. Les tailles des pages peuvent être de 2, 4, 8 ou 16Ko. La taille des pages est définie à la création du serveur et ne peut plus être modifiée par la suite.

Ces pages contiennent des objets de la base de données, notamment :

L'utilisation de plus grandes pages logiques permet de créer des lignes plus longues et ainsi d'améliorer les performances.

La taille de pages logiques (2, 4, 8 ou 16K) détermine l'allocation sur le serveur pour :

Chaque type de page a la taille de la taille de page logique définie au niveau du serveur.

2-1- En-têtes de pages et tailles de page

Toutes les pages comportent un en-tête dans lequel sont stockées des informations telles que l'ID d'objet auquel appartient la page et d'autres données utilisées pour gérer l'espace sur la page.

La taille de l'en-tête est différente selon qu'il s'agisse d'une table en verrouillage AllPages (APL) ou en verrouillage lignes (DOL) : le reste de la page est disponible pour le stockage des lignes de données et d'index. Pour le stockage des données de type text, image ou Java, le comportement est différent et sera traité dans un paragraphe ultérieur.

2-2- Extents

Dans ASE, les pages sont toujours allouées à une table, un index ou une structure LOB. Un bloc de 8 pages s'appelle un extent . La taille d'un extent dépend de la taille de page utilisée par le serveur. Elle est de 16K sur un serveur de 2Ko, 64Ko sur une serveur de 8Ko etc... L'espace minimal que peut occuper une table ou un index est de 1 extent, soit 8 pages. Les extents ne sont désalloués que lorsque toutes les pages de l'extent sont vides.

L'utilisation d'extents dans ASE est transparente pour l'utilisateur, sauf lors de l'examen des rapports sur l'utilisation de l'espace.

Par exemple, les rapports générés par sp_spaceused indiquent l'espace alloué (colonne reserved) et l'espace utilisé par les données et les index. La colonne unused donne l'espace des extents alloués à un objet mais non encore utilisés pour stocker les données.

sp_spaceused  titles
name   rowtotal  reserved   data    index_size    unused
-----  --------  --------   ------  ----------    ------
titles  5000     1392 KB    1250 KB 94 KB         48 KB

Dans le rapport ci-dessus, la table titles et ses index disposent d'un espace réservé de 1392Ko sur divers extents, dont 48Ko (soit 24 pages de données) qui ne sont pas allouées.

3- Pages gérant l'allocation de l'espace

Outre les pages de données, d'index et d'objets LOB utilisées pour le stockage, ASE a recours à d'autres types de pages pour gérer le stockage, contrôler l'allocation de l'espace et organiser les objets de la base de données.

La table sysindexes contient également des pointeurs utilisés lors de l'accès aux données.

Les pages qui gèrent l'allocation de l'espace et les pointeurs sysindexes sont utilisés pour :

Les pages suivantes analysent l'utilisation de l'espace disque par les objets de bases de données :

3-1- Pages de la table d'allocation globale (sysgams, GAM)

Chaque base de données possède une page de table GAM. Elle contient un bitmap de toutes les unités d'allocation d'une base de données, chaque unité étant représentée par un bit. Sous ASE, une unité d'allocation correspond à 256 pages. Lorsqu'il n'existe plus d'extents disponibles pour le stockage d'objets dans une unité d'allocation, le bit correspondant dans la table GAM vaut 1.

Ce système permet d'accélérer l'allocation d'espace aux objets. La page GAM n'est pas visible aux utilisateurs ; elle apparaît dans les catalogues système en tant que table sysgams.

3-2- Pages d'allocation

Lorsqu'une base de données est créée ou que de l'espace est ajouté dans une base de données, l'espace est divisé en unités d'allocation de 256 pages de données. La première page de chaque unité d'allocation est appelée page d'allocation. La page 0 et toutes les pages multiples de 256 sont des pages d'allocation.

La page d'allocation garde en mémoire l'espace de chaque extent de l'unité d'allocation en enregistrant l'ID de l'objet et l'ID de l'index pour l'objet stocké dans l'extent, ainsi que le nombre de pages libres et occupées.

3-3- Pages OAM : pages de la table d'allocation d'objets

Chaque table, index ou chaîne de texte possède une ou plusieurs pages d'OAM (Objet Allocation Map) qui sont stockées sur des pages allouées à la table ou à l'index. Si une table possède plusieurs pages d'OAM, elles sont liées de façon à former une chaîne. Ces pages d'OAM stockent des pointeurs renvoyant aux unités d'allocation qui contiennent les pages de l'objet recherché.

La première page de la chaîne contient les conseils d'allocation, qui indiquent par exemple quelle page d'OAM de la chaîne comporte des informations sur les unités d'allocation disposant d'espace. Cette méthode permet d'allouer rapidement à un objet un supplément d'espace à proximité des pages qu'il occupe déjà.

3-4- Gestion du stockage des objets par les pages d'OAM et les pages d'allocation

La figure illustre la manière dont les unités d'allocation, les extents et les objets sont gérés par les pages d'OAM et les pages d'allocation.

L'allocation de pages permet de ne pas séparer les pages d'un objet. ASE s'efforce de garder ensemble les pages allouées à un objet. En règle générale :

3-5- Table sysindexes et accès aux données

La table sysindexes stocke des informations sur les tables indexées et non indexées. Elle contient une ligne où :

Chaque ligne de sysindexes stocke des pointeurs renvoyant à une table ou à un index afin d'accélérer l'accès aux objets.

Colonne Utilisation pour l'accès aux tables Utilisation pour l'accès aux indexes
root Si indid est égal à 0 et qu'il s'agit d'une table APL, root pointe vers la dernière page de cette table. Sert à retrouver la page racine de l'arbre d'index.
first Renvoie à la première page de données dans le chaînage de pages pour les tables APL. Renvoie à la première page de niveau feuille dans un index non clusterisé ou dans un index clusterisé d'une table DOL.
doampg Renvoie à la première page d'OAM de la table
ioampg Renvoie à la première page d'OAM d'un index.

4- Cas pratiques

Dans les cas pratiques ci-dessous, nous travaillons sur une base de données ayant l'identifiant 5 et on se propose de reconstruire la structure de cette dernière avec les commandes dbcc et plus particulièrement pour la table HISTO.

La table HISTO a l'identifiant 1744006213 et dispose d'un index clusterisé. Le mode de verrouillage de la table HISTO est le mode APL (AllPages).

4-1- Retrouver les pages OAM (Object Allocation Map) et les pages allouées sur les unités d'allocation pour un objet

4-1-1- dbcc listoam

Syntaxe :

dbcc listoam(dbid, table_id, indid)

Dans ce cas pratique on se propose de retrouver les pages OAM de la table HISTO.

dbcc traceon(3604)
go
dbcc listoam(5,1744006213,0)
go
Objid: 1744006213     indid:   0
OAM pg cnt:      1   Entry cnt:          6
Rows:         149998       Rows Per pg:      118
Used pgs:     1273   Unused pgs:         1
Attribute entries:       10
OAM status bits set:  (0x8000 (PG_OAMPG), 0x0008 (PG_OAMATTRIB), 0x0004
(PG_OAMSORT))
LAST SCANNED OAM PAGE:          0
ALLOCATION HINTS     :
  1025          0          0          0
     0          0          0          0
     0          0          0          0
     0          0          0
IDENTITY Max burned value from disk:     NULL From the DES:   NULL
OAM pg #       1025 has the following       6 entries (allocpg:used/unused):

    1024:247/  0      1280:255/  0      1536:255/  0      1792:247/  0
    2048:255/  0      2304: 14/  1

La commande dbcc listoam montre que la table HISTO ne dispose que d'une seule page OAM (OAM pg cnt : 1) qui est la page 1025 (OAM pg # 1025).

La page OAM #1025 pour la table HISTO contient 6 entrées (6 entries) ce qui permet d'en déduire que la table HISTO est répartie sur 6 unités d'allocation (une unité d'allocation = 256 pages).

La fin de la commande dbcc listoam permet d'en déduire les réservations de pages sur les unités d'allocations pour la table HISTO:

Unité d'allocation pages allouées
Unité d'allocation 1 (Page 0 à 255) 0 pages allouées
Unité d'allocation 2 (Page 256 à 511) 0 pages allouées
Unité d'allocation 3 (Page 512 à 767) 0 pages allouées
Unité d'allocation 4 (Page 768 à 1023) 0 pages allouées
Unité d'allocation 5 (Page 1024 à 1279) 247 pages allouées (1024:247/0)
Unité d'allocation 6 (Page 1280 à 1535) 255 pages allouées (1280:255/0)
Unité d'allocation 7 (Page 1536 à 1791) 255 pages allouées (1536:255/0)
Unité d'allocation 8 (Page 1792 à 2047) 247 pages allouées (1792:247/0)
Unité d'allocation 9 (Page 2048 à 2303) 255 pages allouées (2048:255/0)
Unité d'allocation 10 (Page 2304 à 2559) 15 pages allouées dont 1 inutilisée (2304: 14/1)

dbcc listoam(5,1744006213,1)
go
Objid: 1744006213     indid:   1
OAM pg cnt:      1   Entry cnt:          1
Rows:         149998       Rows Per pg:        0
Used pgs:       13   Unused pgs:         3
Attribute entries:       10
OAM status bits set:  (0x8000 (PG_OAMPG), 0x0008 (PG_OAMATTRIB), 0x0004
(PG_OAMSORT))
LAST SCANNED OAM PAGE:          0
ALLOCATION HINTS     :
    1000          0          0          0
       0          0          0          0
       0          0          0          0
       0          0          0
IDENTITY Max burned value from disk:     NULL From the DES:   NULL
OAM pg #       1000 has the following       1 entry (allocpg:used/unused):

     768: 13/  3

La commande dbcc listoam montre que l'index clusterisé de la table HISTO ne dispose que d'une seule page OAM (OAM pg cnt : 1) qui est la page 1000 (OAM pg # 1000).

La page OAM #1000 pour la table HISTO contient qu'une entrée (1 entry) ce qui permet d'en déduire que l'index clusterisé de la table HISTO n'est répartie que sur 1 unité d'allocation (une unité d'allocation = 256 pages).

La fin de la commande dbcc listoam permet d'en déduire les réservations de pages sur les unités d'allocations pour l'index clusterisé de la table HISTO:

Unité d'allocation pages allouées
Unité d'allocation 1 (Page 0 à 255) 0 pages allouées
Unité d'allocation 2 (Page 256 à 511) 0 pages allouées
Unité d'allocation 3 (Page 512 à 767) 0 pages allouées
Unité d'allocation 4 (Page 768 à 1023) 16 pages allouées dont 3 inutilisées (768:13/3)
Unité d'allocation 5 (Page 1024 à 1279) 0 pages allouées

4-1-2- Table sysindexes

La table sysindexes confirme les informations données par la commande dbcc listoam :

> select indid, doampg, ioampg, first, root from sysindexes where object_id(name)='HISTO'
indid doampg     ioampg      first       root
----- ------     ------      -----       ----
1       1025       1000       1026       1001

Dans le cas de la table HISTO, indid vaut 1 car il s'agit d'une table disposant d'un index clusterisé.

Si l'on créé un index non clusterisé sur la table HISTO (idx_ncHISTO) :

> select indid, doampg, ioampg, first, root from sysindexes where object_id(name)='HISTO'
indid  doampg    ioampg      first       root
-----  ------    ------      -----       ----
1       1025       1000       1026       1001
2          0       2320       3648       3396

4-1-3- dbcc page pour retrouver les extents utilisés par les objets dans une unité d'allocation

Dans ce cas pratique on se propose de retrouver les extents utilisés par l'index clusterisé de la table HISTO et la table HISTO sur les unités d'allocation. La commande dbcc page avec Sybase 12.5.2 va fournir toutes ces informations.

dbcc page(dbid | dbname, pageno, [printopt [,cache [,logical [,cachename ]]]])

Les paramètres cache, logical et cachename de la commande dbcc page ne seront pas évoquées dans cette documentation technique.

Pour l'option printopt, deux valeurs possible :

4-1-3-1- Commande dbcc page sur une page de la table ALLOCATION

La commande dbcc page avec Sybase 12.5.2 fournit des informations précieuses sur une unité d'allocation (32 extents) en spécifiant une page de la table ALLOCATION (objid=99). Pour rappel, une page de la table ALLOCATION est un multiple de 256 (0, 256, 512, 768, 1024 etc...).

dbcc page(5,0,1)
go
PAGE HEADER:
Page header for page 0x214DF000
pageno=0 dealloc_count=13 objid=99 dbid=5 timestamp=0000 00000001,
segmap=0x00000003 (0x00000002 (SEG_DEFAULT), 0x00000001 (SYS_SEGMENT))
page status bits: 0x0 (0x0000)
...

pextents[]:
no.  start page   ptn  rsv  fwd  ---  --objid---  alloc deall indid status
  0:          0  0x00 0x00 0x00 0x00           1   0x3f  0x00     0  0x00
  1:          8  0x01 0x00 0x00 0x00           1   0x03  0x00     1  0x00
  2:         16  0x00 0x00 0x00 0x00           3   0xff  0x00     0  0x00
  3:         24  0x00 0x00 0x00 0x00           2   0x7f  0x00     0  0x00
  4:         32  0x00 0x00 0x00 0x00           2   0x03  0x00     1  0x00
  5:         40  0x00 0x00 0x00 0x00           3   0x03  0x00     1  0x00
  6:         48  0x00 0x00 0x00 0x00           4   0x03  0x00     0  0x00
  7:         56  0x00 0x00 0x00 0x00           4   0x03  0x00     1  0x00
  8:         64  0x01 0x00 0x00 0x00           1   0x01  0x00     2  0x01
  9:         72  0x00 0x00 0x00 0x00          14   0xff  0x00     0  0x00
  10:         80  0x01 0x00 0x00 0x00          10   0x03  0x00     2  0x00
  11:         88  0x01 0x00 0x00 0x00           4   0x01  0x00     2  0x01
  12:         96  0x01 0x00 0x00 0x00           4   0x01  0x00     2  0x01
  13:        104  0x01 0x00 0x00 0x00           1   0x01  0x00     2  0x01
  14:        112  0x01 0x00 0x00 0x00           7   0x03  0x00     0  0x00
  15:        120  0x01 0x00 0x00 0x00           5   0x03  0x00     1  0x01
  16:        128  0x01 0x00 0x00 0x00           5   0xff  0x00     0  0x01
  17:        136  0x01 0x00 0x00 0x00           6   0x03  0x00     1  0x01
  18:        144  0x01 0x00 0x00 0x00           6   0x0f  0x00     0  0x01
  19:        152  0x01 0x00 0x00 0x00          21   0x03  0x00   255  0x00
  20:        160  0x01 0x00 0x00 0x00           9   0x03  0x00     1  0x01
  21:        168  0x01 0x00 0x00 0x00           9   0x0f  0x00     0  0x01
  22:        176  0x01 0x00 0x00 0x00          10   0x03  0x00     1  0x01
  23:        184  0x01 0x00 0x00 0x00          10   0x03  0x00     0  0x01
  24:        192  0x01 0x00 0x00 0x00          10   0x03  0x00     3  0x00
  25:        200  0x01 0x00 0x00 0x00          12   0x03  0x00     1  0x01
  26:        208  0x01 0x00 0x00 0x00          11   0x03  0x00     1  0x01
  27:        216  0x01 0x00 0x00 0x00          11   0x03  0x00     0  0x01
  28:        224  0x01 0x00 0x00 0x00          16   0x03  0x00     2  0x00
  29:        232  0x01 0x00 0x00 0x00          12   0x03  0x00     0  0x01
  30:        240  0x01 0x00 0x00 0x00          13   0x03  0x00     1  0x01
  31:        248  0x01 0x00 0x00 0x00          13   0x07  0x00     0  0x01
  
  pextentoampg[]:
             2           0          17          25
            33          41          49          57
            64           0          80          88
            88          64         112         120
           128         136         144         152
           160         168         176         184
           192         200         208         216
           224         232         240         248

Sur la première unité d'allocation, à partir de la rubrique pextents[ ] de la commande dbcc page on peut retirer les informations ci-dessous :

Sur la première unité d'allocation, à partir de la rubrique pextentoampg[ ] de la commande dbcc page on peut déduire toutes les pages d'OAM existant sur les extents, ainsi

4-1-3-2- Commande dbcc page sur une page d'OAM

La commande dbcc page sur une page d'OAM confirme les informations données sur les pages OAM données par la commande dbcc page sur une page de la table ALLOCATION.

dbcc page(5, 17,1)
go
PAGE HEADER:
Page header for page 0x214DF000
pageno=17 nextpg=17 prevpg=17 objid=3 timestamp=0000 00000397
oampgcount=1 attrcount=0 indid=0 totalentries_lo=2 entrycount=2
page status bits: 0x8000 (0x8000 (PG_OAMPG))

Le mot clé PG_OAMPG montre bien que la page #17 est une page d'OAM pour la table ayant l'identifiant 3 (objid=3, indid=0).

La section PAGE HEADER pour cette page d'OAM montre également qu'il n'existe qu'une seule page d'OAM pour la table ayant l'identifiant 3 (objid=3, indid=3) : oampgcount=1 nextpg=17 prevpg=17

Les rubriques nextpg et prevpg indiquent le chaînage de pages pour les pages d'OAM de l'objet : page d'OAM précédente, page d'OAM suivante.

4-1-3-3- Reconstruction de la première unité d'allocation

Avec les informations récupérées plus haut, la première unité d'allocation est facilement reconstruite.

4-1-4- dbcc extentdump pour retrouver les pages allouée et non allouées sur un extent par un objet

Les commandes dbcc listoam et dbcc page permettent de localiser les extents utilisés par un objet sur les unités d'allocation. En revanche, elles ne permettent pas de déterminer finement les pages allouées ou non allouées sur un extent : la commande dbcc extentdump permet de retrouver cette information.

Syntaxe :

dbcc extentdump (dbid , page)

La commande dbcc extentdump rapporte toutes les pages allouées ou non allouées sur l'extent dont fait partie la page indiquée dans la commande.

La commande dbcc listoam sur la table HISTO a remonté sur les unités d'allocation n°9 et n°10 les informations ci-dessous :

Unité d'allocation pages allouées
Unité d'allocation 9 (Page 2048 à 2303) 255 pages allouées (2048:255/0)
Unité d'allocation 10 (Page 2304 à 2559) 15 pages allouées dont 1 inutilisée (2304: 14/1)

Sur l'unité d'allocation n°9 : toutes les pages sont allouées et utilisées par l'objet HISTO.

Sur l'unité d'allocation n°10 : 2 extents sont utilisés par l'object HISTO et sur un des deux extents, une page est non allouée mais il n'est pas précisé sur lequel des deux extents.

La commande dbcc page sur la page d'allocation 2304 indique que ce sont les deux premiers extents qui sont utilisés par la table HISTO dans la 10è unité d'allocation :

> dbcc page(5,2301,1)
PAGE HEADER:
Page header for page 0x214DF000
pageno=2304 dealloc_count=0 objid=99 dbid=5 timestamp=0000 00000001,
segmap=0x00000003 (0x00000002 (SEG_DEFAULT), 0x00000001 (SYS_SEGMENT))
page status bits: 0x0 (0x0000)

...
pextents[]:
no.  start page   ptn  rsv  fwd  ---  --objid---  alloc deall indid status
  0:       2304  0x01 0x00 0x00 0x00  1744006213   0xff  0x00     0  0x01
  1:       2312  0x01 0x00 0x00 0x00  1744006213   0x7f  0x00     0  0x01
  2:       2320  0x00 0x00 0x00 0x00           0   0x00  0x00     0  0x00
  3:       2328  0x00 0x00 0x00 0x00           0   0x00  0x00     0  0x00
  4:       2336  0x00 0x00 0x00 0x00           0   0x00  0x00     0  0x00

La commande dbcc extentdump sur la page 2312 donne alors toutes les informations sur les pages allouées et non allouées sur l'extent n°1 de l'unité d'allocation n°10, extent occupé par la table HISTO :

> dbcc extentdump(5,2312)
DISPLAY EXTENT FOR GIVEN PAGE REQUESTED: 2312
  Extent ID 2312 on allocation page 2304
  Object ID is 1744006213
  Index ID is 0
  Extent Partition ID (Virtual) is 1
  Allocation bitmap: 0x7f ( 2312 2313 2314 2315 2316 2317 2318 )
  Dealloc    bitmap: 0x00 ( )
  Forward    bitmap: 0x00 ( )
  Reserve    bitmap: 0x00 ( )
  status: 0x01 ((0x0001 (EX_SORT)))
  Sort bit is on
  Reference bit is off
  Spacebits  bitmap: 0x00000000
  Page: 2312 (0x00)
  Page: 2313 (0x00)
  Page: 2314 (0x00)
  Page: 2315 (0x00)
  Page: 2316 (0x00)
  Page: 2317 (0x00)
  Page: 2318 (0x00)
  Page: 2319 (0x00)
  Buddy Page for extent (se_extbuddypage): 0

La commande dbcc extentdump indique que la page 2319 qui fait partie de l'extent #1 de l'unité d'allocation n°10 n'est pas référencée dans la section Allocation bitmap: 0x7f ( 2312 2313 2314 2315 2316 2317 2318 ). Ce qui permet d'en déduire qu'il s'agit de la page #2319 qui n'est pas allouée.


Annexe

Historique

Version Date Commentaires
1.0 12/2004 Version initiale

Liens

Sybase BOL Adaptive Server Enterprise 15.0, Understanding page and object allocation concepts
Sybase BOL Adaptive Server Enterprise 15.0, Understanding the object allocation map (OAM)
Sybase BOL Adaptive Server Enterprise 15.0, Understanding page linkage