Eu tenho uma tabela que é de +80 GB com 200 milhões de linhas. Estou tentando agilizar e notei que tem um grande número de colunas varchar. No esquema, seus comprimentos variam de 15 caracteres a 250 caracteres com a maioria definida em 50. O comprimento total de todos os varchars é de 850 bytes. No uso real, muitos dos campos são nulos ou as strings são muito curtas.
Eu sei que o Postgres usa um tamanho de página de 8k. Agora, se eu tiver que fazer uma varredura completa da tabela e assumindo o pior cenário, 8k / 850 = 9,6 registros por página. Passar pela minha tabela completa vai (e leva) muito tempo. Na realidade, no entanto, como a maioria desses campos está vazia, quanto espaço será alocado no disco para esses varchars? Haverá mais registros por página ou o Postgres coloca um pouco de preenchimento apenas para facilitar as atualizações posteriores?
A razão pela qual estou perguntando é porque estou explorando a ideia de melhorar o desempenho chutando o máximo possível das colunas varchars acessadas com pouca frequência desta tabela e para outra que acessaríamos por meio de uma junção.
Qualquer confirmação ou negação da minha lógica é apreciada.
mj
Suas considerações são válidas, mas tudo isso já é feito automaticamente pelo PostgreSQL:
Um valor NULL não ocupa espaço em uma linha da tabela PostgreSQL.
A
varchar
só ocupará tanto espaço quanto o valor realmente tiver bytes. O limite de comprimento (modificador de tipo) não desperdiça espaço.Para linhas muito largas (2000 bytes e acima), os
varchar
s são primeiro compactados e, se o resultado ainda for muito grande, armazenados externamente em uma tabela TOAST . Se você forSELECT
dessa linha, os valores torrados não serão lidos, a menos que você especifique que os valores da coluna são solicitados.Mas se o limite de tamanho de uma linha for 850 bytes, isso será muito pequeno para entrar nesse intervalo.
Você pode verificar o tamanho médio estimado da linha em bytes observando a
width
coluna na saída deEXPLAIN SELECT * FROM tablename
.O PostgreSQL v12 introduziu o
toast_tuple_target
parâmetro de armazenamento que permitiria reduzir o limite de dados TOASTing. Se você ajustar isso, e depois de reescrever a tabela comVACUUM (FULL)
, o PostgreSQL pode armazenar os dados da maneira que você quiser. Então você pode ver se isso realmente melhora o desempenho.