Sybase et exploitation pratique de dbcc procbuf

Logo

Introduction

Le contexte est parfois particulier au sujet des procédures stockées dans Sybase Adaptive Server Enterprise : un utilisateur note une dérive sur le plan d’exécution d’une procédure stockée au cours d’une semaine d’activité. Malheureusement cette procédure stockée n’est pas en cours d’utilisation au moment de l’analyse et on peut logiquement supposer une recompilation régulière de cette procédure stockée pour expliquer la dérive, recompilation qui modifie le plan d’exécution de la procédure stockée (dans notre contexte, une colonne date d’index n’est plus utilisée dans le plan).

L’analyse du cache de procédure avec sp_monitorconfig 'procedure cache size' ne révèle pas de saturation au niveau de ce cache, l’hypothèse de la recompilation est fortement confirmée et liée à l’exécution de commandes sp_recompile sur les objets sollicités dans la procédure stockée qui est recompilée.

Deux informations sont nécessaires pour mener l’analyse même si la procédure stockée en question n’est pas en cours d’exécution :

  • la dernière date de recompilation de la procédure stockée.
  • le plan d’exécution de la procédure stockée.

La commande dbcc non supportée dbcc procbuf donne ces deux informations (date de recompilation et plan d’exécution). La sortie de dbcc procbuf est très verbeuse et il ne faut pas en être effrayé, elle fournit quand même des informations précieuses sur le plan d’exécution dans le cache de procédures et la date de dernière compilation.

Syntaxe et mise en œuvre de dbcc procbuf

La syntaxe pour l’utilisation de dbcc procbuf est la suivante (la trace 3604 est nécessaire) :

dbcc procbuf (dbid, objid, nbufs, printopt = { 0 | 1 } )

La commande dbcc help permet de retrouver la syntaxe de dbcc procbuf.

dbcc traceon(3604)
go
dbcc help ( procbuf )
go

          procbuf( dbid, objid, nbufs, printopt = { 0 | 1 } )
DBCC execution completed. If DBCC printed error messages,
contact a user with System Administrator (SA) role.
Paramètre Description
dbid identifiant de la base de données
objid identifiant de la procédure stockée
nbufs nombre de buffers ou de procédures stockées
printopt options d’affichage , 0 pour le résumé, 1 pour le détail. Avec 1, les plans d’exécution sont notamment affichés.

Quelques exemples d’utilisation :

dbcc procbuf (0,0,0,0) donnera le résumé de toutes les procédures stockées en cache de la base de données courante.

dbcc traceon(3604)
go
dbcc procbuf (0,0,2,0)
go

dbcc procbuf (0,0,2,0) donnera le résumé des 2 premières stockées en cache de la base de données courante.

Voici ci-dessous un exemple allégé de résultat pour la base master avec la commande dbcc procbuf (0,0,0,0) : les procédures stockées en cache de la base master sont triées par ordre MRU => LRU (Most Recent Used vers Least Recent Used en cache), elles sont séparées par le mot clé PROCBUF:

PROCEDURES (in MRU to LRU order):

PROCBUF:
address=0x204F6F24 id=336001197 pbdbid=1
pbplannum=13
pbuid=1 pbihash=0x00000000 pbnhash=0x00000000 pbprev=0x204F700C
pbtimestamp: Feb 23 2007 2:39PM
pbnext=0x204F73AC pbprochdr=0x20EE0000 pbparam=0x00000000pbtype=4
pbstate=1 pbstat=0x0 pbusecnt=0 pbspid=0 pbdes=0x203E96F4
pbxdes=0x00000000
pbname='sp_getmessage' pbprocnum=1
..........
Summary of memory usage:
 Total # of PROCHDRs used : 1
 Total # of pages used : 24
 Total # of bytes used : 48080
 Total # of lost bytes for alignment : 77
 Total # of pages lost for alignment : 0
 Total percentage of memory lost : 0
..........

PROCBUF:
address=0x204F70F4 id=368001311 pbdbid=1
pbplannum=17
pbuid=1 pbihash=0x00000000 pbnhash=0x00000000 pbprev=0x204F72C4
pbtimestamp: Feb 23 2007 2:41PM
pbnext=0x204F6C6C pbprochdr=0x20E91000 pbparam=0x00000000pbtype=4
pbstate=1 pbstat=0x0 pbusecnt=0 pbspid=0 pbdes=0x203EA378
pbxdes=0x00000000
pbname='sp_configure' pbprocnum=1
........
Summary of memory usage:
 Total # of PROCHDRs used : 3
 Total # of pages used : 195
 Total # of bytes used : 398586
 Total # of lost bytes for alignment : 830
 Total # of pages lost for alignment : 0
 Total percentage of memory lost : 0
...........
				
PROCBUF:
address=0x204F6A9C id=352001254 pbdbid=1
pbplannum=3
pbuid=1 pbihash=0x00000000 pbnhash=0x00000000 pbprev=0x204F69B4
pbtimestamp: Feb 23 2007 2:39PM
pbnext=0x204F71DC pbprochdr=0x20E88000 pbparam=0x00000000pbtype=4
pbstate=1 pbstat=0x0 pbusecnt=0 pbspid=0 pbdes=0x203CF9F0
pbxdes=0x00000000
pbname='sp_aux_getsize' pbprocnum=1
........
Summary of memory usage:
 Total # of PROCHDRs used : 1
 Total # of pages used : 23
 Total # of bytes used : 46733
 Total # of lost bytes for alignment : 109
 Total # of pages lost for alignment : 0
 Total percentage of memory lost : 0
........

La sortie de dbcc procbuf (0,0,0,0) pour la base master montre que les procédures stockées sp_getmessage, sp_configure et sp_aux_getsize sont en cache.

Pour chaque procédure stockée, on retrouve l’identifiant de la procédure stockée (id), l’id de la base de données (pbdbid), le nom de la procédure stockée (pbname) et également l’identifiant du plan d’exécution de la procédure stockée (pbplannum).

La date de compilation de la procédure stockée est donnée dans la sortie avec pbtimestamp :

pbtimestamp: Feb 23 2007 2:39PM

La consommation mémoire d’une procédure stockée dans le cache de procédure est également indiquée à la fin du paragraphe. La procédure stockée sp_aux_getsize consomme 46733 bytes dans le cache de procédure :

Total # of bytes used : 46733

Cette consommation mémoire est également donnée en pages utilisées (Total # of pages used).

La somme de toutes les pages utilisées par toutes les procédures stockées en cache (Total # of pages used) s’approche de la valeur Num_active donnée par sp_monitorconfig 'procedure cache size'

execute sp_monitorconfig 'procedure cache size'
go

Usage information at date and time: Feb 23 2007 3:35PM.
Name                   Num_free      Num_active      Pct_act     Max_Used     Num_Reuse
---------------------- ---------    -------------    ---------   ----------   ---------
procedure cache size      1894        1377             42.10        1662              0

Exemple pratique

Dans le cas pratique de l’article, la commande dbcc procbuf est lancée sur la procédure stockée en question qui dérive avec l’option printopt à 1 pour avoir également les éléments sur son plan d’exécution :

dbcc traceon(3604)
go
dbcc procbuf (6,1386715304,0,1)
go

Comme la sortie de dbcc procbuf est très verbeuse, il est même préfèrable de tout déporter dans un fichier avec l’option -o du binaire isql :

isql -Usa -odbcc_procbuf.log
dbcc traceon(3604)
go
dbcc procbuf (6,1386715304,0,1)
go
exit
          PROCEDURES (in MRU to LRU order):
PROCBUF:
address=0x47c12b78 id=1386715304 pbdbid=6
pbplannum=48100
pbuid=1 pbihash=0x0 pbnhash=0x0 pbprev=0x47c0d718
pbtimestamp: Feb 9 2007 10:12AM
pbnext=0x47d259c0 pbprochdr=0x536a4800 pbparam=0x0 pbtype=4
pbstate=1 pbstat=0x0 pbusecnt=0 pbspid=0 pbdes=0x478c21c8pbxdes=0x0
pbname='p_slat_get_assets' pbprocnum=1

La partie pbtimestamp montre bien que la procédure stockée p_slat_get_assets a été recompilée à 10h12 du matin le jour même de l’analyse du problème.

La sortie est très verbeuse avec l’option printopt à 1, toutefois c’est la seule sortie qui permet de retrouver les mots clés du plan d’exécution de la procédure stockée (scan, positioning by key, positioning at table start pour les table scans…) ainsi que les noms des indexes et objets :

MAIN EOP (0x54de15b0):
e_opnext=0x0 e_opsubor=0x0 e_opstatus=(0x00000000)
e_optype= 4 (E_SUBSTITUTE) e_opvar=1 (MATURITY_CLASS_HISTORY) e_opindid=1
(PK_MATURITY_CLASS_HISTORY) e_opscantype=1 e_opscnt=3 e_oporsargcnt=0
e_oprowbuf=0x0, e_opindbuf=0x0
e_opminlen=22 e_oprowfmt=1 (DEF_ROWFORMAT)
(scan type: 1 (SCAN_NORMAL) )
Ascending scan, positioning by key
Keys are:
       INSTRUMENT_ID

Dans le cas pratique de cet article, la procédure stockée a un plan d’exécution qui a dérivé car la colonne MATURITY_CLASS_DATE n’est plus pris en compte sur l’index PK_MATURITY_CLASS_HISTORY de la table MATURITY_CLASS_HISTORY, le bon plan étant le suivant :

MAIN EOP (0x54de15b0):
e_opnext=0x0 e_opsubor=0x0 e_opstatus=(0x00000000)
e_optype= 4 (E_SUBSTITUTE) e_opvar=1 (MATURITY_CLASS_HISTORY) e_opindid=1
(PK_MATURITY_CLASS_HISTORY) e_opscantype=1 e_opscnt=3 e_oporsargcnt=0
e_oprowbuf=0x0, e_opindbuf=0x0
e_opminlen=22 e_oprowfmt=1 (DEF_ROWFORMAT)
(scan type: 1 (SCAN_NORMAL) )
Ascending scan, positioning by key
Keys are:
       INSTRUMENT_ID
       MATURITY_CLASS_DATE

Les statistiques sur la colonne MATURITY_CLASS_DATE étaient en cause dans ce problème et elles ont été recalculées pour retrouver le bon plan d’exécution.