Q2: way to measure page size
PostgreSQL udostępnia szereg funkcji rozmiaru obiektu bazy danych . W tym zapytaniu spakowałem najciekawsze i na dole dodałem kilka funkcji dostępu do statystyk . (Dodatkowy moduł pgstattuple zapewnia jeszcze więcej przydatnych funkcji.)
To pokaże, że różne metody pomiaru „wielkości wiersza” prowadzą do bardzo różnych wyników. Wszystko zależy dokładnie od tego, co chcesz zmierzyć.
To zapytanie wymaga Postgres 9.3 lub nowszego . W przypadku starszych wersji patrz poniżej.
Używanie VALUES
wyrażenia w LATERAL
podzapytaniu , aby uniknąć przeliterowania obliczeń dla każdego wiersza.
Zamień public.tbl
(dwukrotnie) na opcjonalnie kwalifikowaną nazwę tabeli, aby uzyskać kompaktowy widok zebranych statystyk dotyczących wielkości twoich wierszy. Możesz zawinąć to w funkcję plpgsql do wielokrotnego użytku, podać nazwę tabeli jako parametr i użyć 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);
Wynik:
metryczny | bytes / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 MB | 91
mapa widoczności | 0 | 0 bajtów | 0
free_space_map | 32768 | 32 kB | 0
table_size_incl_toast | 44179456 | 42 MB | 91
indexes_size | 33128448 | 32 MB | 68
total_size_incl_toast_and_indexes | 77307904 | 74 MB | 159
live_rows_in_text_representation | 29987360 | 29 MB | 62
------------------------------ | | |
liczba_wierszy | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
W przypadku starszych wersji (Postgres 9.2 lub starszy):
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;
Ten sam wynik.
P1: anything inefficient?
Możesz zoptymalizować kolejność kolumn, aby zaoszczędzić kilka bajtów na wiersz, obecnie zmarnowanych na wypełnienie wyrównania:
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 |
Oszczędza to od 8 do 18 bajtów na wiersz. Nazywam to „kolumną tetris” . Detale:
Weź również pod uwagę:
length(*)
czegoś więcej niż tylkolength(field)
? Wiem, że to znaki nie bajty, ale potrzebuję tylko przybliżonej wartości.