Q2: way to measure page size
PostgreSQL fournit un certain nombre de fonctions de taille d’objet de base de données . J'ai emballé les plus intéressants dans cette requête et ajouté quelques fonctions d'accès aux statistiques en bas. (Le module supplémentaire pgstattuple fournit encore plus de fonctions utiles.)
Cela va montrer que différentes méthodes pour mesurer la "taille d'une ligne" conduisent à des résultats très différents. Tout dépend de ce que vous voulez mesurer, exactement.
Cette requête nécessite Postgres 9.3 ou une version ultérieure . Pour les anciennes versions, voir ci-dessous.
En utilisant une VALUES
expression dans une LATERAL
sous - requête , pour éviter d'épeler les calculs pour chaque ligne.
Remplacez public.tbl
(deux fois) par le nom de votre table, éventuellement qualifié du schéma, pour obtenir une vue compacte des statistiques collectées sur la taille de vos lignes. Vous pouvez envelopper ceci dans une fonction plpgsql pour un usage répété, donner le nom de la table en tant que paramètre et utiliser 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);
Résultat:
métrique | octets / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42 Mo | 91
carte_visibilité | 0 | 0 octet | 0
free_space_map | 32768 | 32 kB | 0
taille_table_incl_toast | 44179456 | 42 Mo | 91
indexes_size | 33128448 | 32 Mo | 68
total_size_incl_toast_and_indexes | 77307904 | 74 Mo | 159
live_rows_in_text_representation | 29987360 | 29 Mo | 62
------------------------------ | | |
nombre_lignes | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
Pour les anciennes versions (Postgres 9.2 ou plus ancien):
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;
Même résultat.
Q1: anything inefficient?
Vous pouvez optimiser l' ordre des colonnes pour économiser quelques octets par ligne, qui sont actuellement perdus pour le remplissage de l'alignement:
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 |
Cela économise entre 8 et 18 octets par ligne. Je l'appelle "tetris de colonne" . Détails:
Considérez également:
length(*)
plutôt que simplementlength(field)
? Je sais que ce ne sont pas des octets, mais j'ai seulement besoin d'une valeur approximative.