Q2 : way to measure page size
PostgreSQL은 많은 데이터베이스 객체 크기 함수를 제공 합니다. 이 쿼리에서 가장 흥미로운 것을 포장 하고 하단에 통계 액세스 기능 을 추가했습니다 . (추가 모듈 pgstattuple 은 더 유용한 기능을 제공합니다.)
이것은 "행의 크기"를 측정하는 다른 방법이 매우 다른 결과를 초래한다는 것을 보여줄 것입니다. 그것은 모두 정확하게 측정하고자하는 것에 달려 있습니다.
이 쿼리에는 Postgres 9.3 이상 이 필요합니다 . 이전 버전의 경우 아래를 참조하십시오.
하위 쿼리 VALUES
에서 표현식을LATERAL
사용하여 모든 행에 대한 계산 철자를 피하십시오.
교체 public.tbl
하여 행의 크기에 대한 수집 된 통계의 컴팩트보기를 얻을 수 있도록 검증을 거친 스키마 테이블 이름 (2 회). 반복 사용을 위해 이것을 plpgsql 함수로 감싸서 테이블 이름을 매개 변수로 사용하고 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);
결과:
메트릭 | 바이트 / ct | bytes_pretty | bytes_per_row
----------------------------------- + ---------- + --- ----------- + ---------------
core_relation_size | 44138496 | 42MB | 91
visible_map | 0 | 0 바이트 | 0
free_space_map | 32768 | 32 킬로바이트 | 0
table_size_incl_toast | 44179456 | 42MB | 91
indexes_size | 33128448 | 32MB | 68
total_size_incl_toast_and_indexes | 77307904 | 74MB | 159
live_rows_in_text_representation | 29987360 | 29MB | 62
------------------------------ | | |
row_count | 483424 | |
live_tuples | 483424 | |
dead_tuples | 2677 | |
이전 버전 (Postgres 9.2 이상) :
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;
같은 결과입니다.
Q1 : anything inefficient?
행 정렬 을 최적화 하여 행당 일부 바이트를 저장하고 현재 정렬 패딩에 낭비되었습니다.
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 |
이는 행당 8-18 바이트를 절약합니다. 나는 그것을 "열 테트리스" 라고 부릅니다 . 세부:
또한 다음을 고려하십시오.
length(*)
그냥 하는 것보다 할 수있는 방법이length(field)
있습니까? 바이트가 아닌 문자이지만 대략적인 값만 필요하다는 것을 알고 있습니다.