Sloupec Tetris
Ve skutečnosti můžete něco udělat , ale to vyžaduje hlubší pochopení. Klíčové slovo je zarovnání odsazení . Každý datový typ má specifické požadavky na zarovnání.
Můžete minimalizovat ztrátu místa kvůli odsazení mezi sloupci tím, že je výhodně nařídí. Následující (extrémní) příklad by plýtval velkým množstvím fyzického místa na disku:
CREATE TABLE t (
e int2 -- 6 bytes of padding after int2
, a int8
, f int2 -- 6 bytes of padding after int2
, b int8
, g int2 -- 6 bytes of padding after int2
, c int8
, h int2 -- 6 bytes of padding after int2
, d int8)
Chcete-li ušetřit 24 bajtů na řádek, použijte místo toho:
CREATE TABLE t (
a int8
, b int8
, c int8
, d int8
, e int2
, f int2
, g int2
, h int2) -- 4 int2 occupy 8 byte (MAXALIGN), no padding at the end
db<>zde hrajte
Starý sqlfiddle
Obecně platí, že pokud dáte 8bajtové sloupce jako první, potom 4bajtové, 2bajtové a 1bajtové sloupce jako poslední, nemůžete udělat chybu.
boolean
, uuid
(!) a několik dalších typů nepotřebuje žádné zarovnávací vycpávky. text
, varchar
a další typy "varlena" (proměnná délka) nominálně vyžadují zarovnání "int" (4 bajty na většině počítačů). Ale nepozoroval jsem žádnou zarovnávací výplň ve formátu disku (na rozdíl od RAM). Nakonec jsem vysvětlení našel v poznámce ve zdrojovém kódu:
Všimněte si také, že při skladování "zabalených" varlen povolujeme porušení nominálního zarovnání; mechanismus TOAST se stará o to, aby to bylo skryto před většinou kódu.
Takže "int" zarovnání je vynuceno pouze tehdy, když (případně komprimovaný) datum obsahující jeden úvodní délkový bajt přesahuje 127 bajtů. Poté se úložiště varlena přepne na čtyři úvodní bajty a vyžaduje zarovnání „int“.
Normálně můžete ušetřit několik bajtů na řádek v nejlepším případě hraním "sloupcového tetris" . Nic z toho není ve většině případů nutné. Ale s miliardami řádků to může snadno znamenat několik gigabajtů.
Skutečnou velikost sloupce/řádku můžete otestovat pomocí funkce pg_column_size()
.
Některé typy zabírají více místa v paměti RAM než na disku (komprimovaný nebo „sbalený“ formát). Při testování stejné hodnoty (nebo řádku hodnot vs. řádku tabulky) pomocí pg_column_size()
můžete získat větší výsledky pro konstanty (formát RAM) než pro sloupce tabulky. .
Nakonec lze některé typy komprimovat nebo „opékat“ (ukládat mimo řádek) nebo obojí.
Režie na n-tici (řádek)
4 bajty na řádek pro identifikátor položky – nepodléhají výše uvedeným úvahám.
A alespoň 24 bajtů (23 + odsazení) pro hlavičku n-tice. Manuál pro rozložení stránky databáze:
K dispozici je hlavička pevné velikosti (zabírá 23 bajtů na většině počítačů), za kterou následuje volitelná nulová bitmapa, volitelné pole ID objektu a uživatelská data.
Pro odsazení mezi hlavičkou a uživatelskými daty potřebujete znát MAXALIGN
na vašem serveru – obvykle 8 bajtů na 64bitovém OS (nebo 4 bajty na 32bitovém OS). Pokud si nejste jisti, podívejte se na pg_controldata
.
Spusťte následující ve svém binárním adresáři Postgres abyste získali definitivní odpověď:
./pg_controldata /path/to/my/dbcluster
Manuál:
Skutečná uživatelská data (sloupce řádku) začínají na offsetu označeném
t_hoff
, což musí být vždy násobek hodnotyMAXALIGN
vzdálenost pro nástupiště.
Optimální úložiště tedy obvykle získáte zabalením dat do násobků 8 bajtů.
Na příkladu, který jste zveřejnili, nemůžete nic získat . Už je pevně zabaleno. 2 bajty odsazení za posledním int2
, 4 bajty na konci. Výplň můžete na konci sloučit na 6 bajtů, což by nic nezměnilo.
Režie na datovou stránku
Velikost datové stránky je obvykle 8 kB. Na této úrovni také nějaká režie / nadýmání:Zbytky nejsou dostatečně velké, aby se vešly další n-tice, a co je důležitější, mrtvé řádky nebo procento vyhrazené pomocí FILLFACTOR
nastavení.
Existuje několik dalších faktorů velikosti disku, které je třeba vzít v úvahu:
- Kolik záznamů mohu uložit do 5 MB PostgreSQL na Heroku?
- Nepoužívá se při použití NULL v PostgreSQL stále bitmapa NULL v záhlaví?
- Konfigurace PostgreSQL pro výkon čtení
Typy polí?
S polí typu, jako byste hodnotili, přidali byste 24 bajtů režie pro typ. Prvky pole navíc zabírají místo jako obvykle. Není co získat.