F.37. pageinspect — низкоуровневое исследование страниц баз данных #
Модуль pageinspect
предоставляет функции, позволяющие исследовать страницы баз данных на низком уровне, что бывает полезно для отладки. Все эти функции могут вызывать только суперпользователи.
F.37.1. Функции общего назначения #
-
get_raw_page(relname text, fork text, blkno bigint) returns bytea
Функция
get_raw_page
считывает указанный блок отношения с заданным именем и возвращает копию значенияbytea
. Это позволяет получить одну согласованную во времени копию блока. В параметреfork
нужно передать'main'
, чтобы обратиться к основному слою данных,'fsm'
— к карте свободного пространства,'vm'
— к карте видимости, либо'init'
— к слою инициализации.-
get_raw_page(relname text, blkno bigint) returns bytea
Упрощённая версия
get_raw_page
для чтения данных из основного слоя. Синонимget_raw_page(relname, 'main', blkno)
-
page_header(page bytea) returns record
Функция
page_header
показывает поля, общие для всех страниц кучи и индекса Postgres Pro.В качестве аргумента ей передаётся образ страницы, полученный в результате вызова
get_raw_page
. Например:test=# SELECT * FROM page_header(get_raw_page('pg_class', 0)); lsn | checksum | flags | lower | upper | special | pagesize | version | xid_base | multi_base | prune_xid -----------+----------+--------+-------+-------+---------+----------+---------+----------+------------+---------- 0/24A1B50 | 0 | 1 | 232 | 368 | 8192 | 8192 | 4 | 0 | 0 | 0
Возвращаемые столбцы соответствуют полям в структуре
PageHeaderData
.Поле
checksum
содержит контрольную сумму, сохранённую для страницы. Эта сумма может быть неверной при повреждении страницы. Если в данном экземпляре кластера контрольные суммы отключены, это значение не имеет смысла.-
page_checksum(page bytea, blkno bigint) returns smallint
Функция
page_checksum
вычисляет контрольную сумму страницы, которая должна была бы находиться в заданном блоке.В качестве аргумента ей передаётся образ страницы, полученный в результате вызова
get_raw_page
. Например:test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0); page_checksum --------------- 13443
Заметьте, что вычисление контрольной суммы зависит от номера блока, поэтому обеим функциям нужно передавать одинаковые номера (за исключением случаев эзотерической отладки).
Контрольную сумму, вычисленную этой функцией, можно сравнить с полем
checksum
результата функцииpage_header
. Если контрольные суммы для текущего экземпляра БД включены, эти значения должны быть равны.-
fsm_page_contents(page bytea) returns text
Функция
fsm_page_contents
показывает внутреннюю структуру узла на странице FSM. Например:test=# SELECT fsm_page_contents(get_raw_page('pg_class', 'fsm', 0));
Данный запрос выводит несколько текстовых строк, по одной строке для каждого узла двоичного дерева на заданной странице. Нулевые узлы при этом пропускаются. Также выводится так называемый указатель «вперёд», который указывает на следующий слот, получаемый с этой страницы.
F.37.2. Функции для исследования кучи #
-
heap_page_items(page bytea) returns setof record
Функция
heap_page_items
показывает все указатели линейных блоков на странице кучи. Для используемых блоков также выводятся заголовки кортежей. При этом показываются все кортежи, независимо от того, были ли видны они в снимке MVCC в момент копирования исходной страницы.В качестве аргумента ей передаётся образ страницы кучи, полученный в результате вызова
get_raw_page
. Например:test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));
Распаковать биты флагов
t_infomask
иt_infomask2
для кортежей кучи позволяет функцияheap_tuple_infomask_flags
.-
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
разделяет данные кортежей на атрибуты так, как это происходит внутри сервера.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));
В качестве аргументов этой функции должны передаваться атрибуты, возвращаемые функцией
heap_page_items
.Если параметр
do_detoast
равенtrue
, полученные атрибуты будут распакованы по мере необходимости. Если он не задан, подразумеваетсяfalse
.-
heap_page_item_attrs(page bytea, rel_oid regclass [, do_detoast bool]) returns setof record
Функция
heap_page_item_attrs
похожа наheap_page_items
, но возвращает неструктурированное содержимое кортежа в виде массива атрибутов, которые могут быть распакованы, если установлен флагdo_detoast
(по умолчанию они не распаковываются).В качестве аргумента ей передаётся образ страницы кучи, полученный в результате вызова
get_raw_page
. Например: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
декодирует значенияt_infomask
иt_infomask2
, которые возвращает функцияheap_page_items
, и выдаёт массивы с именами флагов в понятном человеку виде: один, перечисляющий все флаги по отдельности, а другой — комбинированные. Например: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;
Вызывая эту функцию, ей следует передавать в аргументах те атрибуты, которые возвращает
heap_page_items
.Комбинированные флаги выводятся для тех макросов на уровне исходного кода, в которых объединяются значения нескольких битов, например
HEAP_XMIN_FROZEN
.
F.37.3. Функции для индексов-B-деревьев #
-
bt_metap(relname text) returns record
bt_metap
выдаёт информацию о метастранице индекса B-дерево. Например: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
выдаёт сводную информацию по странице данных индекса-B-дерева. Например: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
выдаёт ту же информацию, что иbt_page_stats
, но для каждой страницы диапазона страниц, начиная сblkno
дляblk_count
страниц. При отрицательном значенииblk_count
информация выводится для всех страниц, начиная сblkno
до конца индекса. Например: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
выдаёт подробную информацию обо всех элементах на странице индекса B-дерево. Например: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)
Это листовая страница B-дерева. В ней все кортежи, относящиеся к таблице, оказались кортежами со списками идентификаторов (каждый содержит 100 шестибайтных идентификаторов). Помимо них, по смещению
itemoffset
1 находится кортеж «верхний ключ». В данном примереctid
содержит закодированную информацию о каждом кортеже, хотя на уровне листьев записи часто содержат вctid
непосредственно TID кучи. Вtids
содержатся идентификаторы (TID) в виде списка идентификаторов.На внутренней странице (она здесь не показана), компонент номера блока в
ctid
содержит «ссылку вниз», то есть номер блока другой страницы в самом индексе. Компонент смещения (второе число) вctid
содержит закодированную информацию о кортеже, в частности, количество столбцов в нём (при отсечении суффикса ненужные конечные столбцы могут быть отброшены). Когда столбцы отбрасываются, считается, что они содержат значение «минус бесконечность».В столбце
htid
показывается TID кортежа в куче, вне зависимости от его нижележащего представления. Это значение должно совпадать сctid
или может быть декодировано из альтернативного представления, применяющегося в списках идентификаторов и в кортежах на внутренних страницах. В кортежах на внутренних страницах столбец с TID кучи на уровне реализации обычно отсутствует, что выглядит как значение NULL в столбцеhtid
.Заметьте, что первый элемент в любой, кроме самой правой, странице (то есть в любой странице с ненулевым значением в поле
btpo_next
) представляет собой «верхний ключ», то есть его полеdata
задаёт верхнюю границу для всех элементов, находящихся на странице, а полеctid
не указывает на другой блок. Кроме того, на внутренних страницах в первом действительном элементе данных (в первом элементе после верхнего ключа) обязательно будут отброшены все столбцы, и поэтому полеdata
не будет содержать фактического значения. Однако такой элемент содержит в своём полеctid
корректную ссылку вниз.За дополнительной информацией о структуре индексов-B-деревьев обратитесь к Подразделу 64.1.4.1. Об исключении дубликатов и о списках идентификаторов подробнее рассказывается в Подразделе 64.1.4.3.
-
bt_page_items(page bytea) returns setof record
Функции
bt_page_items
также можно передать страницу в виде значенияbytea
. Для получения образа страницы, который она может принять, следует использовать функциюget_raw_page
. Так, последний пример можно переписать следующим образом: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)
В остальном данная функция работает так, как описано выше.
F.37.4. Функции для индексов BRIN #
-
brin_page_type(page bytea) returns text
Функция
brin_page_type
возвращает тип страницы для заданной страницы индекса BRIN или выдаёт ошибку, если эта страница не является корректной страницей индекса BRIN. Например:test=# SELECT brin_page_type(get_raw_page('brinidx', 0)); brin_page_type ---------------- meta
-
brin_metapage_info(page bytea) returns record
Функция
brin_metapage_info
возвращает разнообразные сведения о метастранице индекса BRIN. Например: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
выдаёт список идентификаторов кортежей со страницы сопоставлений зон индекса BRIN. Например: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
выдаёт содержимое, сохранённое в странице данных BRIN. Например: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}
Возвращаемые столбцы соответствуют полям в структурах
BrinMemTuple
иBrinValues
.
F.37.5. Функции для индексов GIN #
-
gin_metapage_info(page bytea) returns record
Функция
gin_metapage_info
выдаёт информацию о метастранице индекса GIN. Например: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
выдаёт информацию из непрозрачной области индекса GIN, например, тип страницы. Например: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
выдаёт информацию о данных, хранящихся в сжатой странице индекса GIN на уровне листьев. Например: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)
F.37.6. Функции для индексов GiST #
-
gist_page_opaque_info(page bytea) returns record
Функция
gist_page_opaque_info
выдаёт информацию из непрозрачной области страницы индекса GiST, например значения NSN, rightlink и тип страницы. Например: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
возвращает информацию о данных, хранящихся на странице индекса GiST. Например: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
Функция работает так же, как
gist_page_items
, но возвращает данные ключа в виде неразобранных двоичных данныхbytea
. Поскольку она не пытается декодировать ключ, ей не требуется знать, какой индекс задействован. Например: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)
F.37.7. Функции для хеш-индексов #
-
hash_page_type(page bytea) returns text
Функция
hash_page_type
возвращает тип страницы для заданной страницы хеш-индекса. Например: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
возвращает информацию о странице группы или переполнения хеш-индекса. Например: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
возвращает информацию о данных, хранящихся на странице группы или переполнения хеш-индекса. Например: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
показывает состояние бита в странице битовой карты для определённой страницы переполнения хеш-индекса. Например: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
возвращает информацию, хранящуюся в метастранице хеш-индекса. Например: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}