De PG DOC
pg_column_size(any): número de bytes usados para armazenar um determinado valor (possivelmente compactado) pg_column_size mostra o espaço usado para armazenar qualquer valor de dado individual
Exemplo:
select pg_column_size(5::smallint); -- 2 bytes
select pg_column_size(5::int); -- 4 bytes
Com a entrada de pg_column_size, pode ser uma coluna ou linha, então criei um teste para verificar isso. Aqui está o meu teste:
Minha mesa
CREATE TABLE index_test
(
id integer NOT NULL, -- 4 bytes
a integer, -- 4 bytes
b integer, -- 4 bytes
CONSTRAINT index_test_id PRIMARY KEY (id)
)
1/ Primeira consulta: sum(pg_column_size(table.rows))
with abc as
(
select id,a,b
from index_test where b > 100
)
select pg_size_pretty(sum(pg_column_size(abc.*))) from abc -- "348 kB", abc.* = record
E a explicação da consulta:
"Aggregate (cost=427.55..427.56 rows=1 width=24) (actual time=9.171..9.171 rows=1 loops=1)"
" CTE abc"
" -> Seq Scan on index_test (cost=0.00..180.00 rows=9902 width=12) (actual time=0.039..2.882 rows=9902 loops=1)"
" Filter: (b > 100)"
" -> CTE Scan on abc (cost=0.00..198.04 rows=9902 width=24) (actual time=0.047..7.151 rows=9902 loops=1)"
"Total runtime: 9.376 ms"
2/ Segunda consulta: sum(pg_column_size(table.id)) + sum(pg_column_size(table.a)) + sum(pg_column_size(table.b))
with abc as
(
select id, a, b
from index_test where b > 100
)
select pg_size_pretty((sum(pg_column_size(id))) + (sum(pg_column_size(b))) + (sum(pg_column_size(a))))
from abc -- "116 kB"
E a explicação da consulta:
"Aggregate (cost=526.57..526.59 rows=1 width=12) (actual time=10.959..10.959 rows=1 loops=1)"
" CTE abc"
" -> Seq Scan on index_test (cost=0.00..180.00 rows=9902 width=12) (actual time=0.035..2.780 rows=9902 loops=1)"
" Filter: (b > 100)"
" -> CTE Scan on abc (cost=0.00..198.04 rows=9902 width=12) (actual time=0.039..5.623 rows=9902 loops=1)"
"Total runtime: 11.173 ms"
3. Resultados:
Primeira consulta: 348 KB
Segunda consulta: 116 KB ( pg_column_size(id) = 39 KB ...)
Eu pensei que ambas as consultas deveriam retornar o mesmo resultado, mas tamanho da primeira consulta = 3 * tamanho da segunda consulta, isso me deixou confuso. Na primeira explicação, a "largura = 24 bytes/linha" (em vez de 12), me perguntei por que aumenta, acho que é a pista para a pergunta. Até agora, não consigo encontrar respostas claras para minha pergunta, por favor me ajude.
A diferença de 24 bytes/linha chama a atenção: é do mesmo tamanho que o cabeçalho da linha em tabelas e índices. O que eu não percebi até sua pergunta é que o mesmo tamanho de cabeçalho se aplica aparentemente a todas as linhas que você retorna em uma consulta:
mas
Ao passar uma linha para
pg_column_size()
, ele calcula o tamanho de toda a linha, incluindo o cabeçalho.Agora, jogando um pouco mais com isso, existem alguns fatos interessantes que você pode encontrar.
Por exemplo, pode-se verificar a diferença causada pelo preenchimento das colunas até os 4 bytes mais próximos (onde k é um inteiro positivo):
Aqui temos mais dois bytes do que no primeiro exemplo, os 2 bytes restantes depois que o smallint foi 'desperdiçado'. Isso pode ser importante ao escolher a ordem das colunas em tabelas enormes - por exemplo, podemos espremer algo naquele espaço 'vazio':
A outra coisa importante é que as colunas que têm NULL como valor têm tamanho zero aqui:
Por outro lado, você obterá NULL como resultado ao tentar adicionar a coluna individualmente: