Q2: way to measure page size
PostgreSQL offre una serie di funzioni per la dimensione degli oggetti del database . Ho impacchettato i più interessanti in questa query e ho aggiunto alcune funzioni di accesso alle statistiche in basso. (Il modulo aggiuntivo pgstattuple fornisce ancora funzioni più utili.)
Questo mostrerà che metodi diversi per misurare la "dimensione di una riga" portano a risultati molto diversi. Tutto dipende esattamente da cosa vuoi misurare.
Questa query richiede Postgres 9.3 o successivo . Per le versioni precedenti vedi sotto.
Utilizzando VALUES
un'espressione in una LATERAL
sottoquery , per evitare di sillabare i calcoli per ogni riga.
Sostituisci public.tbl
(due volte) con il nome della tabella facoltativamente qualificato per ottenere una visione compatta delle statistiche raccolte sulla dimensione delle tue righe. Puoi avvolgerlo in una funzione plpgsql per un uso ripetuto, inserire il nome della tabella come parametro e usare 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);
Risultato:
metrica | byte / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 MB | 91
visibilità_map | 0 | 0 byte | 0
free_space_map | 32768 | 32 kB | 0
table_size_incl_toast | 44179456 | 42 MB | 91
dimensione_indice | 33128448 | 32 MB | 68
total_size_incl_toast_and_indexes | 77307904 | 74 MB | 159
live_rows_in_text_representation | 29987360 | 29 MB | 62
------------------------------ | | |
row_count | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
Per le versioni precedenti (Postgres 9.2 o precedenti):
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;
Stesso risultato
Q1: anything inefficient?
È possibile ottimizzare l' ordine delle colonne per risparmiare alcuni byte per riga, attualmente sprecato per il riempimento di allineamento:
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 |
Ciò consente di risparmiare tra 8 e 18 byte per riga. Lo chiamo "colonna tetris" . Dettagli:
Considera anche:
length(*)
piuttosto che sololength(field)
? So che i caratteri non sono byte ma ho solo bisogno di un valore approssimativo.