Q2: way to measure page size
PostgreSQL надає ряд функцій розміру об'єкта бази даних . Я упакував найцікавіші з цього запиту і додав кілька функцій доступу до статистики внизу. (Додатковий модуль pgstattuple надає ще корисні функції.)
Це покаже, що різні методи вимірювання "розміру рядка" призводять до дуже різних результатів. Все залежить від того, що ви хочете точно виміряти.
Для цього запиту потрібен Postgres 9.3 або пізнішої версії . Старіші версії див. Нижче.
Використовуючи VALUES
вираз у LATERAL
підзапиті , щоб уникнути написання обчислень для кожного рядка.
Замініть public.tbl
(двічі) назви за таблицею, що відповідають вимогам схеми, щоб отримати компактне уявлення про зібрану статистику щодо розміру рядків. Ви можете зафіксувати це у функції plpgsql для багаторазового використання, введіть назву таблиці як параметр і використовуйте EXECUTE
...
SELECT l.metric, l.nr AS "bytes/ct"
, CASE WHEN is_size THEN pg_size_pretty(nr) END AS bytes_pretty
, CASE WHEN is_size THEN nr / NULLIF(x.ct, 0) END AS bytes_per_row
FROM (
SELECT min(tableoid) AS tbl -- = 'public.tbl'::regclass::oid
, count(*) AS ct
, sum(length(t::text)) AS txt_len -- length in characters
FROM public.tbl t -- provide table name *once*
) x
, LATERAL (
VALUES
(true , 'core_relation_size' , pg_relation_size(tbl))
, (true , 'visibility_map' , pg_relation_size(tbl, 'vm'))
, (true , 'free_space_map' , pg_relation_size(tbl, 'fsm'))
, (true , 'table_size_incl_toast' , pg_table_size(tbl))
, (true , 'indexes_size' , pg_indexes_size(tbl))
, (true , 'total_size_incl_toast_and_indexes', pg_total_relation_size(tbl))
, (true , 'live_rows_in_text_representation' , txt_len)
, (false, '------------------------------' , NULL)
, (false, 'row_count' , ct)
, (false, 'live_tuples' , pg_stat_get_live_tuples(tbl))
, (false, 'dead_tuples' , pg_stat_get_dead_tuples(tbl))
) l(is_size, metric, nr);
Результат:
метричні | байт / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 Мб | 91
vidibility_map | 0 | 0 байт | 0
free_space_map | 32768 | 32 кБ | 0
table_size_incl_toast | 44179456 | 42 Мб | 91
indexes_size | 33128448 | 32 Мб | 68
total_size_incl_toast_and_indexes | 77307904 | 74 Мб | 159
live_rows_in_text_representation | 29987360 | 29 Мб | 62
------------------------------ | | |
рядок_рахунок | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
Для старих версій (Postgres 9.2 або новіші):
WITH x AS (
SELECT count(*) AS ct
, sum(length(t::text)) AS txt_len -- length in characters
, 'public.tbl'::regclass AS tbl -- provide table name as string
FROM public.tbl t -- provide table name as name
), y AS (
SELECT ARRAY [pg_relation_size(tbl)
, pg_relation_size(tbl, 'vm')
, pg_relation_size(tbl, 'fsm')
, pg_table_size(tbl)
, pg_indexes_size(tbl)
, pg_total_relation_size(tbl)
, txt_len
] AS val
, ARRAY ['core_relation_size'
, 'visibility_map'
, 'free_space_map'
, 'table_size_incl_toast'
, 'indexes_size'
, 'total_size_incl_toast_and_indexes'
, 'live_rows_in_text_representation'
] AS name
FROM x
)
SELECT unnest(name) AS metric
, unnest(val) AS "bytes/ct"
, pg_size_pretty(unnest(val)) AS bytes_pretty
, unnest(val) / NULLIF(ct, 0) AS bytes_per_row
FROM x, y
UNION ALL SELECT '------------------------------', NULL, NULL, NULL
UNION ALL SELECT 'row_count', ct, NULL, NULL FROM x
UNION ALL SELECT 'live_tuples', pg_stat_get_live_tuples(tbl), NULL, NULL FROM x
UNION ALL SELECT 'dead_tuples', pg_stat_get_dead_tuples(tbl), NULL, NULL FROM x;
Той самий результат.
Q1: anything inefficient?
Ви можете оптимізувати порядок стовпців, щоб зберегти кілька байтів у рядку, витрачених на даний момент для вирівнювання.
integer | not null default nextval('core_page_id_seq'::regclass)
integer | not null default 0
character varying(255) | not null
character varying(64) | not null
text | default '{}'::text
character varying(255) |
text | default '{}'::text
text |
timestamp with time zone |
timestamp with time zone |
integer |
integer |
Це економить від 8 до 18 байт у рядку. Я називаю це «стовпчик тетрису» . Деталі:
Також врахуйте:
length(*)
а не простоlength(field)
? Я знаю, що знаки не байти, але мені потрібно лише приблизно значення.