El módulo pageinspect proporciona funciones que te permiten
inspeccionar el contenido de las páginas de las bases de datos a bajo nivel, lo cual es útil para
fines de depuración. Todas estas funciones solo pueden ser utilizadas por superusuarios.
get_raw_page(relname text, fork text, blkno bigint) returns bytea
get_raw_page lee el bloque especificado de la relación
indicada y devuelve una copia como un valor bytea. Esto permite obtener
una única copia coherente en el tiempo del bloque.
fork debe ser 'main' para
la bifurcación de datos principal (main fork), 'fsm' para el
mapa de espacio libre (free space map),
'vm' para el
mapa de visibilidad (visibility map) o
'init' para la bifurcación de inicialización (initialization fork).
get_raw_page(relname text, blkno bigint) returns bytea
Una versión abreviada de get_raw_page, para leer
de la bifurcación principal. Equivalente a
get_raw_page(relname, 'main', blkno).
page_header(page bytea) returns record
page_header muestra los campos que son comunes a todas
las páginas de índices y del heap de PostgreSQL.
Se debe pasar como argumento una imagen de página obtenida con get_raw_page.
Por ejemplo:
test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
lsn | checksum | flags | lower | upper | special | pagesize | version | prune_xid
-----------+----------+--------+-------+-------+---------+----------+---------+-----------
0/24A1B50 | 0 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0
Las columnas devueltas corresponden a los campos en la estructura
PageHeaderData.
Consulta src/include/storage/bufpage.h para más detalles.
El campo checksum es la suma de comprobación (checksum) almacenada en
la página, que podría ser incorrecta si la página está de alguna manera corrompida. Si
las sumas de comprobación de datos están desactivadas para esta instancia, entonces el valor almacenado
carece de significado.
page_checksum(page bytea, blkno bigint) returns smallint
page_checksum calcula la suma de comprobación para la página, como si
estuviera ubicada en el bloque indicado.
Se debe pasar como argumento una imagen de página obtenida con get_raw_page.
Por ejemplo:
test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0);
page_checksum
---------------
13443
Ten en cuenta que la suma de comprobación depende del número de bloque, por lo que se deben pasar números de bloques coincidentes (excepto cuando se realiza una depuración esotérica).
La suma de comprobación calculada con esta función se puede comparar con
el campo de resultado checksum de la
función page_header. Si las sumas de comprobación de datos están
activadas para esta instancia, los dos valores deberían ser iguales.
fsm_page_contents(page bytea) returns text
fsm_page_contents muestra la estructura interna de nodos
de una página FSM. Por ejemplo:
test=# SELECT fsm_page_contents(get_raw_page('pg_class', 'fsm', 0));
La salida es una cadena multilínea, con una línea por cada nodo del árbol binario dentro de la página. Solo se imprimen aquellos nodos que no son cero. También se imprime el puntero llamado "next", que apunta a la siguiente ranura (slot) que será devuelta por la página.
Consulta src/backend/storage/freespace/README para obtener más
información sobre la estructura de una página FSM.
heap_page_items(page bytea) returns setof record
heap_page_items muestra todos los punteros de línea en una página
del heap. Para aquellos punteros de línea que están en uso, también se muestran las cabeceras de
las tuplas y los datos sin procesar de las mismas (raw data). Se muestran todas las tuplas, independientemente
de si eran visibles para una instantánea MVCC en el momento en que se copió la página sin procesar.
Se debe pasar como argumento una imagen de página del heap obtenida con get_raw_page.
Por ejemplo:
test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));
Consulta src/include/storage/itemid.h y
src/include/access/htup_details.h para obtener explicaciones de los campos
devueltos.
La función heap_tuple_infomask_flags se puede utilizar
para desempaquetar los bits de flag de t_infomask
y t_infomask2 para tuplas del heap.
tuple_data_split(rel_oid oid, t_data bytea, t_infomask integer, t_infomask2 integer, t_bits text [, do_detoast bool]) returns bytea[]
tuple_data_split divide los datos de la tupla en atributos
de la misma manera que lo hacen los componentes internos del backend.
test=# SELECT tuple_data_split('pg_class'::regclass, t_data, t_infomask, t_infomask2, t_bits) FROM heap_page_items(get_raw_page('pg_class', 0));
Esta función debe llamarse con los mismos argumentos que los atributos devueltos
por heap_page_items.
Si do_detoast es true,
los atributos se descomprimirán/desasociarán (detoasted) según sea necesario. El valor por defecto es
false.
heap_page_item_attrs(page bytea, rel_oid regclass [, do_detoast bool]) returns setof record
heap_page_item_attrs es equivalente a
heap_page_items excepto que devuelve
los datos sin procesar de la tupla como un array de atributos que opcionalmente
pueden ser procesados con detoast por do_detoast, el cual es
false por defecto.
Se debe pasar como argumento una imagen de página del heap obtenida con get_raw_page.
Por ejemplo:
test=# SELECT * FROM heap_page_item_attrs(get_raw_page('pg_class', 0), 'pg_class'::regclass);
heap_tuple_infomask_flags(t_infomask integer, t_infomask2 integer) returns record
heap_tuple_infomask_flags decodifica los valores de
t_infomask y
t_infomask2 devueltos por
heap_page_items en un conjunto legible por humanos
de arrays formados por nombres de flags, con una columna para todos
los flags y otra para los flags combinados. Por ejemplo:
test=# SELECT t_ctid, raw_flags, combined_flags
FROM heap_page_items(get_raw_page('pg_class', 0)),
LATERAL heap_tuple_infomask_flags(t_infomask, t_infomask2)
WHERE t_infomask IS NOT NULL OR t_infomask2 IS NOT NULL;
Esta función debe llamarse con los mismos argumentos que los atributos de retorno
de heap_page_items.
Los flags combinados se muestran para macros a nivel de código fuente que tienen en
cuenta el valor de más de un bit sin procesar, como
HEAP_XMIN_FROZEN.
Consulta src/include/access/htup_details.h para obtener
explicaciones de los nombres de los flags devueltos.
bt_metap(relname text) returns record
bt_metap devuelve información sobre la metapágina de un
índice B-tree. Por ejemplo:
test=# SELECT * FROM bt_metap('pg_cast_oid_index');
-[ RECORD 1 ]-------------+-------
magic | 340322
version | 4
root | 1
level | 0
fastroot | 1
fastlevel | 0
last_cleanup_num_delpages | 0
last_cleanup_num_tuples | 230
allequalimage | f
bt_page_stats(relname text, blkno bigint) returns record
bt_page_stats devuelve información resumida sobre
una página de datos de un índice B-tree. Por ejemplo:
test=# SELECT * FROM bt_page_stats('pg_cast_oid_index', 1);
-[ RECORD 1 ]-+-----
blkno | 1
type | l
live_items | 224
dead_items | 0
avg_item_size | 16
page_size | 8192
free_size | 3668
btpo_prev | 0
btpo_next | 0
btpo_level | 0
btpo_flags | 3
bt_multi_page_stats(relname text, blkno bigint, blk_count bigint) returns setof record
bt_multi_page_stats devuelve la misma información
que bt_page_stats, pero lo hace para cada página en el
rango de páginas que comienza en blkno y se extiende
durante blk_count páginas.
Si blk_count es negativo, se reportan todas las páginas
desde blkno hasta el final del índice. Por ejemplo:
test=# SELECT * FROM bt_multi_page_stats('pg_proc_oid_index', 5, 2);
-[ RECORD 1 ]-+-----
blkno | 5
type | l
live_items | 367
dead_items | 0
avg_item_size | 16
page_size | 8192
free_size | 808
btpo_prev | 4
btpo_next | 6
btpo_level | 0
btpo_flags | 1
-[ RECORD 2 ]-+-----
blkno | 6
type | l
live_items | 367
dead_items | 0
avg_item_size | 16
page_size | 8192
free_size | 808
btpo_prev | 5
btpo_next | 7
btpo_level | 0
btpo_flags | 1
bt_page_items(relname text, blkno bigint) returns setof record
bt_page_items devuelve información detallada sobre
todos los elementos de una página de índice B-tree. Por ejemplo:
test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids
FROM bt_page_items('tenk2_hundred', 5);
itemoffset | ctid | itemlen | nulls | vars | data | dead | htid | some_tids
------------+-----------+---------+-------+------+-------------------------+------+--------+---------------------
1 | (16,1) | 16 | f | f | 30 00 00 00 00 00 00 00 | | |
2 | (16,8292) | 616 | f | f | 24 00 00 00 00 00 00 00 | f | (1,6) | {"(1,6)","(10,22)"}
3 | (16,8292) | 616 | f | f | 25 00 00 00 00 00 00 00 | f | (1,18) | {"(1,18)","(4,22)"}
4 | (16,8292) | 616 | f | f | 26 00 00 00 00 00 00 00 | f | (4,18) | {"(4,18)","(6,17)"}
5 | (16,8292) | 616 | f | f | 27 00 00 00 00 00 00 00 | f | (1,2) | {"(1,2)","(1,19)"}
6 | (16,8292) | 616 | f | f | 28 00 00 00 00 00 00 00 | f | (2,24) | {"(2,24)","(4,11)"}
7 | (16,8292) | 616 | f | f | 29 00 00 00 00 00 00 00 | f | (2,17) | {"(2,17)","(11,2)"}
8 | (16,8292) | 616 | f | f | 2a 00 00 00 00 00 00 00 | f | (0,25) | {"(0,25)","(3,20)"}
9 | (16,8292) | 616 | f | f | 2b 00 00 00 00 00 00 00 | f | (0,10) | {"(0,10)","(0,14)"}
10 | (16,8292) | 616 | f | f | 2c 00 00 00 00 00 00 00 | f | (1,3) | {"(1,3)","(3,9)"}
11 | (16,8292) | 616 | f | f | 2d 00 00 00 00 00 00 00 | f | (6,28) | {"(6,28)","(11,1)"}
12 | (16,8292) | 616 | f | f | 2e 00 00 00 00 00 00 00 | f | (0,27) | {"(0,27)","(1,13)"}
13 | (16,8292) | 616 | f | f | 2f 00 00 00 00 00 00 00 | f | (4,17) | {"(4,17)","(4,21)"}
(13 rows)
Esta es una página hoja de un B-tree. Todas las tuplas que apuntan a la tabla
resultan ser tuplas de tipo posting list (todas ellas almacenan un total de
100 TIDs de 6 bytes). También hay una tupla “high key” (clave alta)
en el itemoffset número 1.
En este ejemplo se utiliza ctid para almacenar información
codificada sobre cada tupla, aunque las tuplas de página hoja
suelen almacenar un TID del heap directamente en el
campo ctid.
tids es la lista de TIDs almacenada como una
posting list.
En una página interna (no mostrada), la parte del número de bloque de
ctid es un “downlink” (enlace descendente),
que es el número de bloque de otra página del propio índice.
La parte de desplazamiento (el segundo número) de
ctid almacena información codificada sobre
la tupla, como el número de columnas presentes (la truncación
de sufijos puede haber eliminado columnas de sufijo innecesarias). Las columnas
truncadas se tratan como si tuvieran el valor “menos
infinito”.
htid muestra un TID de heap para la tupla,
independientemente de la representación de la tupla subyacente. Este valor
puede coincidir con ctid, o puede ser decodificado
a partir de las representaciones alternativas utilizadas por las tuplas de tipo posting list
y las tuplas de páginas internas. Las tuplas en páginas internas
suelen tener la columna TID del heap de nivel de implementación truncada,
lo que se representa como un valor htid NULL.
Ten en cuenta que el primer elemento en cualquier página que no sea la de más a la derecha (cualquier página con
un valor distinto de cero en el campo btpo_next) es la
“high key” de la página, lo que significa que sus datos (data)
sirven como un límite superior para todos los elementos que aparecen en la página, mientras que
su campo ctid no apunta a
otro bloque. Además, en las páginas internas, el primer elemento de datos reales
(el primer elemento que no es una clave alta) tiene de manera confiable todas las
columnas truncadas, no dejando ningún valor real en su campo
data. Sin embargo, dicho elemento sí tiene un
downlink válido en su campo ctid.
Para obtener más detalles sobre la estructura de los índices B-tree, consulta Section 65.1.4.1. Para obtener más detalles sobre la deduplicación y las posting lists, consulta la Section 65.1.4.3.
bt_page_items(page bytea) returns setof record
También es posible pasar una página a bt_page_items
como un valor bytea. Se debe pasar como argumento una imagen de página obtenida
con get_raw_page. Por lo tanto, el
último ejemplo también podría reescribirse de esta manera:
test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids
FROM bt_page_items(get_raw_page('tenk2_hundred', 5));
itemoffset | ctid | itemlen | nulls | vars | data | dead | htid | some_tids
------------+-----------+---------+-------+------+-------------------------+------+--------+---------------------
1 | (16,1) | 16 | f | f | 30 00 00 00 00 00 00 00 | | |
2 | (16,8292) | 616 | f | f | 24 00 00 00 00 00 00 00 | f | (1,6) | {"(1,6)","(10,22)"}
3 | (16,8292) | 616 | f | f | 25 00 00 00 00 00 00 00 | f | (1,18) | {"(1,18)","(4,22)"}
4 | (16,8292) | 616 | f | f | 26 00 00 00 00 00 00 00 | f | (4,18) | {"(4,18)","(6,17)"}
5 | (16,8292) | 616 | f | f | 27 00 00 00 00 00 00 00 | f | (1,2) | {"(1,2)","(1,19)"}
6 | (16,8292) | 616 | f | f | 28 00 00 00 00 00 00 00 | f | (2,24) | {"(2,24)","(4,11)"}
7 | (16,8292) | 616 | f | f | 29 00 00 00 00 00 00 00 | f | (2,17) | {"(2,17)","(11,2)"}
8 | (16,8292) | 616 | f | f | 2a 00 00 00 00 00 00 00 | f | (0,25) | {"(0,25)","(3,20)"}
9 | (16,8292) | 616 | f | f | 2b 00 00 00 00 00 00 00 | f | (0,10) | {"(0,10)","(0,14)"}
10 | (16,8292) | 616 | f | f | 2c 00 00 00 00 00 00 00 | f | (1,3) | {"(1,3)","(3,9)"}
11 | (16,8292) | 616 | f | f | 2d 00 00 00 00 00 00 00 | f | (6,28) | {"(6,28)","(11,1)"}
12 | (16,8292) | 616 | f | f | 2e 00 00 00 00 00 00 00 | f | (0,27) | {"(0,27)","(1,13)"}
13 | (16,8292) | 616 | f | f | 2f 00 00 00 00 00 00 00 | f | (4,17) | {"(4,17)","(4,21)"}
(13 rows)
Todos los demás detalles son los mismos explicados en el elemento anterior.
brin_page_type(page bytea) returns text
brin_page_type devuelve el tipo de página de la página de
índice BRIN dada, o lanza un error si la página
no es una página BRIN válida. Por ejemplo:
test=# SELECT brin_page_type(get_raw_page('brinidx', 0));
brin_page_type
----------------
meta
brin_metapage_info(page bytea) returns record
brin_metapage_info devuelve información diversa
sobre una metapágina de índice BRIN. Por ejemplo:
test=# SELECT * FROM brin_metapage_info(get_raw_page('brinidx', 0));
magic | version | pagesperrange | lastrevmappage
------------+---------+---------------+----------------
0xA8109CFA | 1 | 4 | 2
brin_revmap_data(page bytea) returns setof tid
brin_revmap_data devuelve la lista de identificadores
de tuplas en una página de mapa de rango de índice BRIN (range map page).
Por ejemplo:
test=# SELECT * FROM brin_revmap_data(get_raw_page('brinidx', 2)) LIMIT 5;
pages
---------
(6,137)
(6,138)
(6,139)
(6,140)
(6,141)
brin_page_items(page bytea, index oid) returns setof record
brin_page_items devuelve los datos almacenados en la
página de datos BRIN. Por ejemplo:
test=# SELECT * FROM brin_page_items(get_raw_page('brinidx', 5),
'brinidx')
ORDER BY blknum, attnum LIMIT 6;
itemoffset | blknum | attnum | allnulls | hasnulls | placeholder | empty | value
------------+--------+--------+----------+----------+-------------+-------+--------------
137 | 0 | 1 | t | f | f | f |
137 | 0 | 2 | f | f | f | f | {1 .. 88}
138 | 4 | 1 | t | f | f | f |
138 | 4 | 2 | f | f | f | f | {89 .. 176}
139 | 8 | 1 | t | f | f | f |
139 | 8 | 2 | f | f | f | f | {177 .. 264}
Las columnas devueltas corresponden a los campos en las estructuras
BrinMemTuple y BrinValues.
Consulta src/include/access/brin_tuple.h para más detalles.
gin_metapage_info(page bytea) returns record
gin_metapage_info devuelve información sobre
una metapágina de índice GIN. Por ejemplo:
test=# SELECT * FROM gin_metapage_info(get_raw_page('gin_index', 0));
-[ RECORD 1 ]----+-----------
pending_head | 4294967295
pending_tail | 4294967295
tail_free_size | 0
n_pending_pages | 0
n_pending_tuples | 0
n_total_pages | 7
n_entry_pages | 6
n_data_pages | 0
n_entries | 693
version | 2
gin_page_opaque_info(page bytea) returns record
gin_page_opaque_info devuelve información sobre
el área opaca de un índice GIN, como el tipo de página.
Por ejemplo:
test=# SELECT * FROM gin_page_opaque_info(get_raw_page('gin_index', 2));
rightlink | maxoff | flags
-----------+--------+------------------------
5 | 0 | {data,leaf,compressed}
(1 row)
gin_leafpage_items(page bytea) returns setof record
gin_leafpage_items devuelve información sobre
los datos almacenados en una página hoja GIN comprimida. Por ejemplo:
test=# SELECT first_tid, nbytes, tids[0:5] AS some_tids
FROM gin_leafpage_items(get_raw_page('gin_test_idx', 2));
first_tid | nbytes | some_tids
-----------+--------+----------------------------------------------------------
(8,41) | 244 | {"(8,41)","(8,43)","(8,44)","(8,45)","(8,46)"}
(10,45) | 248 | {"(10,45)","(10,46)","(10,47)","(10,48)","(10,49)"}
(12,52) | 248 | {"(12,52)","(12,53)","(12,54)","(12,55)","(12,56)"}
(14,59) | 320 | {"(14,59)","(14,60)","(14,61)","(14,62)","(14,63)"}
(167,16) | 376 | {"(167,16)","(167,17)","(167,18)","(167,19)","(167,20)"}
(170,30) | 376 | {"(170,30)","(170,31)","(170,32)","(170,33)","(170,34)"}
(173,44) | 197 | {"(173,44)","(173,45)","(173,46)","(173,47)","(173,48)"}
(7 rows)
gist_page_opaque_info(page bytea) returns record
gist_page_opaque_info devuelve información del
área opaca de una página de índice GiST, como el NSN,
el rightlink y el tipo de página.
Por ejemplo:
test=# SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
lsn | nsn | rightlink | flags
-----+-----+-----------+--------
0/1 | 0/0 | 1 | {leaf}
(1 row)
gist_page_items(page bytea, index_oid regclass) returns setof record
gist_page_items devuelve información sobre
los datos almacenados en una página de un índice GiST. Por ejemplo:
test=# SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 0), 'test_gist_idx');
itemoffset | ctid | itemlen | dead | keys
------------+-----------+---------+------+-------------------------------
1 | (1,65535) | 40 | f | (p)=("(185,185),(1,1)")
2 | (2,65535) | 40 | f | (p)=("(370,370),(186,186)")
3 | (3,65535) | 40 | f | (p)=("(555,555),(371,371)")
4 | (4,65535) | 40 | f | (p)=("(740,740),(556,556)")
5 | (5,65535) | 40 | f | (p)=("(870,870),(741,741)")
6 | (6,65535) | 40 | f | (p)=("(1000,1000),(871,871)")
(6 rows)
gist_page_items_bytea(page bytea) returns setof record
Lo mismo que gist_page_items, pero devuelve los datos de la clave
como un blob bytea sin procesar. Dado que no intenta decodificar
la clave, no necesita saber de qué índice se trata. Por
ejemplo:
test=# SELECT * FROM gist_page_items_bytea(get_raw_page('test_gist_idx', 0));
itemoffset | ctid | itemlen | dead | key_data
------------+-----------+---------+------+------------------------------------------------------------------------------------
1 | (1,65535) | 40 | f | \x00000100ffff28000000000000c064400000000000c06440000000000000f03f000000000000f03f
2 | (2,65535) | 40 | f | \x00000200ffff28000000000000c074400000000000c074400000000000e064400000000000e06440
3 | (3,65535) | 40 | f | \x00000300ffff28000000000000207f400000000000207f400000000000d074400000000000d07440
4 | (4,65535) | 40 | f | \x00000400ffff28000000000000c084400000000000c084400000000000307f400000000000307f40
5 | (5,65535) | 40 | f | \x00000500ffff28000000000000f089400000000000f089400000000000c884400000000000c88440
6 | (6,65535) | 40 | f | \x00000600ffff28000000000000208f400000000000208f400000000000f889400000000000f88940
7 | (7,65535) | 40 | f | \x00000700ffff28000000000000408f400000000000408f400000000000288f400000000000288f40
(7 rows)
hash_page_type(page bytea) returns text
hash_page_type devuelve el tipo de página de
la página de índice HASH dada. Por ejemplo:
test=# SELECT hash_page_type(get_raw_page('con_hash_index', 0));
hash_page_type
----------------
metapage
hash_page_stats(page bytea) returns setof record
hash_page_stats devuelve información sobre
un cubo (bucket) o una página de desbordamiento (overflow page) de un índice HASH.
Por ejemplo:
test=# SELECT * FROM hash_page_stats(get_raw_page('con_hash_index', 1));
-[ RECORD 1 ]---+-----------
live_items | 407
dead_items | 0
page_size | 8192
free_size | 8
hasho_prevblkno | 4096
hasho_nextblkno | 8474
hasho_bucket | 0
hasho_flag | 66
hasho_page_id | 65408
hash_page_items(page bytea) returns setof record
hash_page_items devuelve información sobre
los datos almacenados en un cubo o una página de desbordamiento de un
índice HASH. Por ejemplo:
test=# SELECT * FROM hash_page_items(get_raw_page('con_hash_index', 1)) LIMIT 5;
itemoffset | ctid | data
------------+-----------+------------
1 | (899,77) | 1053474816
2 | (897,29) | 1053474816
3 | (894,207) | 1053474816
4 | (892,159) | 1053474816
5 | (890,111) | 1053474816
hash_bitmap_info(index oid, blkno bigint) returns record
hash_bitmap_info muestra el estado de un bit
en la página de mapa de bits para una página de desbordamiento particular de un
índice HASH. Por ejemplo:
test=# SELECT * FROM hash_bitmap_info('con_hash_index', 2052);
bitmapblkno | bitmapbit | bitstatus
-------------+-----------+-----------
65 | 3 | t
hash_metapage_info(page bytea) returns record
hash_metapage_info devuelve información almacenada
en la metapágina de un índice HASH. Por ejemplo:
test=# SELECT magic, version, ntuples, ffactor, bsize, bmsize, bmshift,
test-# maxbucket, highmask, lowmask, ovflpoint, firstfree, nmaps, procid,
test-# regexp_replace(spares::text, '(,0)*}', '}') as spares,
test-# regexp_replace(mapp::text, '(,0)*}', '}') as mapp
test-# FROM hash_metapage_info(get_raw_page('con_hash_index', 0));
-[ RECORD 1 ]-------------------------------------------------------------------------------
magic | 105121344
version | 4
ntuples | 500500
ffactor | 40
bsize | 8152
bmsize | 4096
bmshift | 15
maxbucket | 12512
highmask | 16383
lowmask | 8191
ovflpoint | 28
firstfree | 1204
nmaps | 1
procid | 450
spares | {0,0,0,0,0,0,1,1,1,1,1,1,1,1,3,4,4,4,45,55,58,59,508,567,628,704,1193,1202,1204}
mapp | {65}