Q2: way to measure page size
PostgreSQL proporciona una serie de funciones de tamaño de objeto de base de datos . Empaqué los más interesantes en esta consulta y agregué algunas funciones de acceso a estadísticas en la parte inferior. (El módulo adicional pgstattuple proporciona aún más funciones útiles).
Esto mostrará que los diferentes métodos para medir el "tamaño de una fila" conducen a resultados muy diferentes. Todo depende de lo que quieras medir, exactamente.
Esta consulta requiere Postgres 9.3 o posterior . Para versiones anteriores ver más abajo.
Usar una VALUES
expresión en una LATERAL
subconsulta para evitar deletrear cálculos para cada fila
Reemplace public.tbl
(dos veces) con el nombre de la tabla opcionalmente calificado por el esquema para obtener una vista compacta de las estadísticas recopiladas sobre el tamaño de sus filas. Puede envolver esto en una función plpgsql para uso repetido, entregar el nombre de la tabla como parámetro y usar 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);
Resultado:
métrica | bytes / ct | bytes_pretty | bytes_por_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 MB | 91 91
visibilidad_mapa | 0 | 0 bytes | 0 0
free_space_map | 32768 | 32 kB | 0 0
table_size_incl_toast | 44179456 | 42 MB | 91 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 62
------------------------------ | El | El |
row_count | 483424 | El |
live_tuples | 483424 | El |
dead_tuples | 2677 | El |
Para versiones anteriores (Postgres 9.2 o anterior):
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;
Mismo resultado.
Q1: anything inefficient?
Puede optimizar el orden de las columnas para guardar algunos bytes por fila, actualmente desperdiciados en el relleno de alineación:
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 |
Esto ahorra entre 8 y 18 bytes por fila. Lo llamo "columna tetris" . Detalles:
Considere también:
length(*)
lugar de sololength(field)
? Sé que son caracteres, no bytes, pero solo necesito un valor aproximado.