Слои
-
Проверьте наличие слоев
FSMиVMдля таблиц.postgres@ts_db=# SELECT pg_relation_filepath(tablename::regclass) from pg_catalog.pg_tables where tablename ~ '^i_.$' \g (tuples_only=on format=unaligned) | sed 's/\(^.*$\)/ls -l \$PGDATA\/\1*/' | bashРазбор команды
SELECT pg_relation_filepath(tablename::regclass)— получение относительного пути к файлу данных таблицы; приведениеtablename::regclassпреобразует имя таблицы в рег-тип, требуемый функциейpg_relation_filepath();from pg_catalog.pg_tables where tablename ~ '^i_.$'— выборка из каталогаpg_tablesтаблиц с именами, соответствующими регулярному выражению^i_.$(начинаются сi_и заканчиваются одним символом);\g (tuples_only=on format=unaligned) |— метакоманда, которая передает вывод SQL-запроса через конвейер в команду ОС, отключая заголовки и выравнивание;sed 's/\(^.*$\)/ls -l \$PGDATA\/\1*/'— потоковый редактор, который для каждой полученной строки (относительного пути) конструирует командуls -l $PGDATA/<путь>/*, заменяя путь с помощью\1;| bash— выполняет сформированныеsedкоманды в оболочкеbash, выводя подробную информацию обо всех файлах (слоях) таблицы, включаяmain,fsm,vmи другие.
-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436Пока имеются лишь основные слои таблиц —
main. -
Выполните команду очистки и снова проверьте наличие слоев.
postgres@ts_db=# VACUUM;VACUUMpostgres@ts_db=# SELECT pg_relation_filepath(tablename::regclass) from pg_catalog.pg_tables where tablename ~ '^i_.$' \g (tuples_only=on format=unaligned) | sed 's/\(^.*$\)/ls -l \$PGDATA\/\1*/' | bash-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433-rw------- 1 postgres postgres 24576 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433_fsm-rw------- 1 postgres postgres 8192 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433_vm-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436-rw------- 1 postgres postgres 24576 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436_fsm-rw------- 1 postgres postgres 8192 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436_vmПосле выполнения
VACUUMу обеих таблиц (16433и16436) появились дополнительные слои:fsm(Free Space Map, 24 КБ) иvm(Visibility Map, 8 КБ). Слойfsmхранит информацию о свободном пространстве внутри страниц для ускорения вставки. Слойvmотслеживает видимость строк для всех активных транзакций. -
Сравните полученные размеры с данными, возвращаемыми функцией
pg_relation_size().postgres@ts_db=# SELECT pg_relation_size(16433, 'main'), pg_relation_size(16433, 'fsm'), pg_relation_size(16433, 'vm');pg_relation_size | pg_relation_size | pg_relation_size------------------+------------------+------------------8192 | 24576 | 8192(1 row)postgres@ts_db=# SELECT pg_relation_size(16436, 'main'), pg_relation_size(16436, 'fsm'), pg_relation_size(16436, 'vm');pg_relation_size | pg_relation_size | pg_relation_size------------------+------------------+------------------8192 | 24576 | 8192(1 row) -
Вставьте в таблицы по 100000 строк и снова повторите измерение.
postgres@ts_db=# INSERT INTO i_f SELECT g.i, random() FROM generate_series(1,100000) as g(i);INSERT 0 100000postgres@ts_db=# INSERT INTO i_t SELECT g.i, random()::text FROM generate_series(1,100000) as g(i);INSERT 0 100000postgres@ts_db=# SELECT pg_relation_size(16433, 'main'), pg_relation_size(16433, 'fsm'), pg_relation_size(16433, 'vm');pg_relation_size | pg_relation_size | pg_relation_size------------------+------------------+------------------4431872 | 24576 | 8192(1 row)postgres@ts_db=# SELECT pg_relation_size(16436, 'main'), pg_relation_size(16436, 'fsm'), pg_relation_size(16436, 'vm');pg_relation_size | pg_relation_size | pg_relation_size------------------+------------------+------------------5275648 | 24576 | 8192(1 row)Для таблицы
i_f(OID 16433) слойmainзанимает 4 431 872 байта (~4 МБ),fsm— 24 576 байт (24 КБ),vm— 8 192 байта (8 КБ). Для таблицыi_t(OID 16436)main— 5 275 648 байт (~5 МБ),fsmиvm— те же 24 КБ и 8 КБ. Размеры слоевfsmиvmсовпали с физическими файлами на диске. Рост размераmainу обеих таблиц обусловлен вставленными строками: таблицаi_tзанимает больше места из-за текстового столбца с большими значениями, хранимыми в TOAST.
Самопроверка
Вопрос 1
В сеансе psql выполнены команды:
postgres@ts_db=# VACUUM;
postgres@ts_db=# SELECT pg_relation_filepath(tablename::regclass) from pg_catalog.pg_tables where tablename ~ '^i_.$' //g (tuples_only=on format=unaligned) | sed 's/\(^.*$\)/ls -l \$PGDATA\/\1*/' | bash
-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433
-rw------- 1 postgres postgres 24576 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433_fsm
-rw------- 1 postgres postgres 8192 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16433_vm
-rw------- 1 postgres postgres 8192 Nov 10 10:28 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436
-rw------- 1 postgres postgres 24576 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436_fsm
-rw------- 1 postgres postgres 8192 Nov 10 11:05 /pgdata/06/data/pg_tblspc/16431/PG_15_202310091/16432/16436_vm
Какие слои появились в файловой системе после выполнения VACUUM?
Вопрос 2
В сеансе psql выполнены команды:
postgres@ts_db=# VACUUM;
postgres@ts_db=# SELECT pg_relation_size(16433, 'vm');
pg_relation_size
------------------
8192
(1 row)
postgres@ts_db=# INSERT INTO i_f SELECT g.i, random() FROM generate_series(1,100000) as g(i);
postgres@ts_db=# SELECT pg_relation_size(16433, 'vm');
pg_relation_size
------------------
8192
(1 row)
Почему размер слоя vm остался 8192 байт после вставки 100000 строк?
Вопрос 3
В сеансе psql выполнены команды:
postgres@ts_db=# INSERT INTO i_f SELECT g.i, random() FROM generate_series(1,100000) as g(i);
postgres@ts_db=# INSERT INTO i_t SELECT g.i, random()::text FROM generate_series(1,100000) as g(i);
postgres@ts_db=# SELECT pg_relation_size(16433, 'main') AS i_f_main, pg_relation_size(16436, 'main') AS i_t_main;
i_f_main | i_t_main
-----------+-----------
4431872 | 5275648
Почему слой main таблицы i_t больше, чем у i_f, хотя в обе таблицы вставлено одинаковое количество строк?