pageinspect — низкоуровневый анализ страниц базы данных#
Примечание
Эта страница переведена при помощи нейросети GigaChat.
Модуль pageinspect предоставляет функции, которые позволяют просматривать содержимое страниц базы данных на низком уровне, что полезно для целей отладки. Все эти функции могут использоваться только суперпользователями.
Функции общего назначения#
get_raw_page(relname text, fork text, blkno bigint) returns byteaget_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 recordpage_headerотображает поля, общие для всех страниц кучи и индекса PostgreSQL.Образ страницы, полученный с помощью
get_raw_page, должен быть передан в качестве аргумента. Например: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Возвращаемые столбцы соответствуют полям в структуре
PageHeaderData. См.src/include/storage/bufpage.hдля получения подробной информации.Поле
checksum– это контрольная сумма, хранящаяся на странице, которая может быть неверной, если страница каким-то образом повреждена. Если контрольные суммы данных не включены для этого экземпляра, то сохраняемое значение бессмысленно.page_checksum(page bytea, blkno bigint) returns smallintpage_checksumвычисляет контрольную сумму для страницы так, как если бы она находилась в данном блоке.Образ страницы, полученный с помощью
get_raw_pageдолжен быть передан в качестве аргумента. Например:test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0); page_checksum --------------- 13443Обратите внимание, что контрольная сумма зависит от номера блока, поэтому должны передаваться соответствующие номера блоков (за исключением случаев, когда выполняется эзотерическая отладка).
Контрольная сумма, вычисленная этой функцией, может быть сопоставлена с результатом поля функции
checksumpage_header. Если для этого экземпляра включены контрольные суммы данных, то два значения должны быть равны.fsm_page_contents(page bytea) returns textfsm_page_contentsпоказывает внутреннюю структуру узла страницы FSM. Например:test=# SELECT fsm_page_contents(get_raw_page('pg_class', 'fsm', 0));Вывод представляет собой многострочную строку с одной строкой для каждого узла в двоичном дереве внутри страницы. Печатаются только те узлы, которые не равны нулю. Также печатается так называемый указатель «следующий», который указывает на следующий слот, который будет возвращен со страницы.
См.
src/backend/storage/freespace/READMEдля получения дополнительной информации о структуре страницы FSM.
Функции для исследования кучи#
heap_page_items(page bytea) returns setof recordheap_page_itemsпоказывает все указатели строк на странице кучи. Для тех указателей строк, которые используются, также отображаются заголовки кортежей и сырые данные кортежа. Показываются все кортежи независимо от того, были ли кортежи видны мгновенному снимку MVCC во время копирования исходной страницы.Образ страницы кучи, полученный с помощью
get_raw_page, должен быть передан в качестве аргумента. Например:test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));См.
src/include/storage/itemid.hиsrc/include/access/htup_details.hдля объяснения возвращаемых полей.Функция
heap_tuple_infomask_flagsможет использоваться для распаковки флаговых битовt_infomaskиt_infomask2для кортежей куч.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 recordheap_page_item_attrsэквивалентенheap_page_items, за исключением того, что он возвращает необработанные данные кортежа в виде массива атрибутов, которые могут быть опционально детостированы с помощьюdo_detoast, который по умолчанию равенfalse.Образ страницы кучи, полученный с помощью
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 recordheap_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.См.
src/include/access/htup_details.hдля объяснений возвращаемых имен флагов.
Функции для индексов B-дерева#
bt_metap(relname text) returns recordbt_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 | fbt_page_stats(relname text, blkno bigint) returns recordbt_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 | 3bt_multi_page_stats(relname text, blkno bigint, blk_count bigint) returns setof recordbt_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 | 1bt_page_items(relname text, blkno bigint) returns setof recordbt_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 шестибайтовых идентификаторов TID). Также есть кортеж «верхний ключ» под номером
itemoffset1. В этом примере используетсяctidдля хранения закодированной информации о каждом кортеже, хотя кортежи на листовой странице часто хранят TID кучи непосредственно в полеctid.tids– это список TID, хранящихся в виде списка сообщений.На внутренней странице (она здесь не показана), компонент номера блока в ctid содержит «ссылку вниз», который представляет собой номер блока другой страницы в самом индексе. Часть смещения (второе число)
ctidхранит закодированную информацию о кортеже, такую как количество присутствующих столбцов (обрезка суффикса может удалить ненужные столбцы суффиксов). Обрезанные столбцы рассматриваются как имеющие значение «минус бесконечность».htidпоказывает TID кучи для кортежа независимо от базового представления кортежа. Это значение может совпадать сctid, или может быть декодировано из альтернативных представлений, используемых кортежами списка сообщений и кортежами внутренних страниц. Кортежи во внутренних страницах обычно имеют усеченный столбец TID уровня реализации кучи, что представлено значениемNULLhtid.Обратите внимание, что первый элемент на любой странице, не являющейся самой правой (любая страница с ненулевым значением в поле
btpo_next) является ключом страницы «верхний ключ», что означает, что егоdataслужит верхней границей для всех элементов, появляющихся на странице, тогда как егоctidполе не указывает на другой блок. Кроме того, на внутренних страницах первый реальный элемент данных (первый элемент, который не является высоким ключом) надежно имеет все столбцы, усеченные до нуля, оставляя нулевое значение в егоdataполе. Однако такой элемент действительно имеет допустимую нисходящую ссылку в своемctidполе.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)Все остальные детали такие же, как объяснялось в предыдущем пункте.
Функции для индексов BRIN#
brin_page_type(page bytea) returns textbrin_page_typeвозвращает тип страницы данного индекса BRIN, или генерирует ошибку, если страница не является допустимой страницей BRIN. Например:test=# SELECT brin_page_type(get_raw_page('brinidx', 0)); brin_page_type ---------------- metabrin_metapage_info(page bytea) returns recordbrin_metapage_infoвозвращает разнообразную информацию о метастранице индекса BRIN. Например:test=# SELECT * FROM brin_metapage_info(get_raw_page('brinidx', 0)); magic | version | pagesperrange | lastrevmappage ------------+---------+---------------+---------------- 0xA8109CFA | 1 | 4 | 2brin_revmap_data(page bytea) returns setof tidbrin_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 recordbrin_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. См. src/include/access/brin_tuple.h для получения подробной информации.
Функции для индексов GIN#
gin_metapage_info(page bytea) returns recordgin_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 | 2gin_page_opaque_info(page bytea) returns recordgin_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 recordgin_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)
Функции для индексов GiST#
gist_page_opaque_info(page bytea) returns recordgist_page_opaque_infoвозвращает информацию из непрозрачной области страницы индекса GiST, такой как NSN, правая ссылка и тип страницы. Например: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 recordgist_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, но возвращает данные ключа в виде необработанногоbyteaBLOB. Поскольку она не пытается декодировать ключ, ей не нужно знать, какой индекс участвует. Например: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 texthash_page_typeвозвращает тип страницы для заданной страницы хеш-индекса. Например:test=# SELECT hash_page_type(get_raw_page('con_hash_index', 0)); hash_page_type ---------------- metapagehash_page_stats(page bytea) returns setof recordhash_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 | 65408hash_page_items(page bytea) returns setof recordhash_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) | 1053474816hash_bitmap_info(index oid, blkno bigint) returns recordhash_bitmap_infoотображает состояние бита в битовой карте для определенной страницы переполнения хеш-индекса. Например:test=# SELECT * FROM hash_bitmap_info('con_hash_index', 2052); bitmapblkno | bitmapbit | bitstatus -------------+-----------+----------- 65 | 3 | thash_metapage_info(page bytea) returns recordhash_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}