Q2: way to measure page size
PostgreSQL bietet eine Reihe von Funktionen für die Größe von Datenbankobjekten . Ich habe die interessantesten in dieser Abfrage gepackt und unten einige Statistik-Zugriffsfunktionen hinzugefügt . (Das Zusatzmodul pgstattuple bietet noch weitere nützliche Funktionen.)
Dies wird zeigen, dass verschiedene Methoden zur Messung der "Größe einer Zeile" zu sehr unterschiedlichen Ergebnissen führen. Alles hängt davon ab, was Sie genau messen möchten.
Diese Abfrage erfordert Postgres 9.3 oder höher . Für ältere Versionen siehe unten.
Verwenden eines VALUES
Ausdrucks in einer LATERAL
Unterabfrage , um zu vermeiden, dass Berechnungen für jede Zeile geschrieben werden.
Ersetzen Sie public.tbl
(zweimal) durch Ihren optionalen schemaqualifizierten Tabellennamen, um eine kompakte Ansicht der gesammelten Statistiken über die Größe Ihrer Zeilen zu erhalten. Sie können dies zur wiederholten Verwendung in eine plpgsql-Funktion einbinden, den Tabellennamen als Parameter übergeben und 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);
Ergebnis:
metrisch | Bytes / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 MB | 91
sichtbarkeitskarte | 0 | 0 Bytes | 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
------------------------------ | | |
row_count | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
Für ältere Versionen (Postgres 9.2 oder älter):
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;
Gleiches Ergebnis.
Q1: anything inefficient?
Sie können die Spaltenreihenfolge optimieren , um einige Bytes pro Zeile zu sparen, die derzeit für das Ausrichtungs-Padding verschwendet werden:
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 |
Dies spart zwischen 8 und 18 Bytes pro Zeile. Ich nenne es "Spalte Tetris" . Einzelheiten:
Beachten Sie auch:
length(*)
anstatt es nur zu tunlength(field)
? Ich weiß, dass Zeichen keine Bytes sind, aber ich brauche nur einen ungefähren Wert.