sql >> Database teknologi >  >> RDS >> PostgreSQL

Beregning og pladsbesparelse i PostgreSQL

"Kolonne Tetris"

Faktisk kan du gøre noget , men dette kræver en dybere forståelse. Søgeordet er justeringspolstring . Hver datatype har specifikke tilpasningskrav.

Du kan minimere plads tabt ved udfyldning mellem kolonner ved at bestille dem positivt. Følgende (ekstremt) eksempel ville spilde en masse fysisk diskplads:

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)

For at gemme 24 bytes række, brug i stedet:

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<>spil her
Gamle sqlfiddle

Som en tommelfingerregel, hvis du sætter 8-byte kolonner først, derefter 4-byte, 2-byte og 1-byte kolonner sidst, kan du ikke gå galt.

boolean , uuid (!) og et par andre typer behøver ingen justering polstring. text , varchar og andre typer "varlena" (variabel længde) nominelt kræver "int"-justering (4 bytes på de fleste maskiner). Men jeg observerede ingen justering af polstring i diskformat (i modsætning til i RAM). Til sidst fandt jeg forklaringen i en note i kildekoden:

Bemærk også, at vi tillader, at den nominelle justering bliver overtrådt ved opbevaring af "pakkede" varlenaer; TOAST-mekanismen sørger for at skjule det for det meste kode.

Så "int"-justering håndhæves kun, når det (muligvis komprimerede) datum inklusive en enkelt ledende længde-byte overstiger 127 bytes. Derefter skifter varlena storage til fire førende bytes og kræver "int"-justering.

Normalt kan du i bedste fald spare et par bytes pr. række ved at spille "kolonnetetris" . Intet af dette er nødvendigt i de fleste tilfælde. Men med milliarder af rækker kan det nemt betyde et par gigabyte.

Du kan teste den faktiske kolonne-/rækkestørrelse med funktionen pg_column_size() .
Nogle typer optager mere plads i RAM end på disk (komprimeret eller "pakket" format). Du kan få større resultater for konstanter (RAM-format) end for tabelkolonner, når du tester den samme værdi (eller række af værdier vs. tabelrække) med pg_column_size() .

Endelig kan nogle typer komprimeres eller "ristes" (lagres ude af linjen) eller begge dele.

Overhead pr. tupel (række)

4 bytes pr. række for element-id'en - ikke underlagt ovenstående overvejelser.
Og mindst 24 bytes (23 + udfyldning) for tuple-headeren. Manualen om databasesidelayout:

Der er en header med fast størrelse (optager 23 bytes på de fleste maskiner), efterfulgt af en valgfri null bitmap, et valgfrit objekt-id-felt og brugerdataene.

For udfyldning mellem overskrift og brugerdata skal du kende MAXALIGN på din server - typisk 8 bytes på et 64-bit OS (eller 4 bytes på et 32-bit OS). Hvis du ikke er sikker, så tjek pg_controldata .

Kør følgende i din Postgres binære mappe for at få et endeligt svar:

./pg_controldata /path/to/my/dbcluster

Manualen:

De faktiske brugerdata (rækkens kolonner) begynder med forskydningen angivet af t_hoff , som altid skal være et multiplum af MAXALIGN afstand til platformen.

Så du får typisk lageret optimalt ved at pakke data i multipla af 8 bytes.

Der er intet at vinde i det eksempel, du postede . Det er allerede pakket tæt. 2 bytes udfyldning efter den sidste int2 , 4 bytes til sidst. Du kunne konsolidere udfyldningen til 6 bytes i slutningen, hvilket ikke ville ændre noget.

Overhead pr. dataside

Datasidestørrelsen er typisk 8 KB. Noget overhead / oppustethed på dette niveau også:Rester er ikke store nok til at passe til en anden tupel, og endnu vigtigere døde rækker eller en procentdel reserveret med FILLFACTOR indstilling.

Der er et par andre faktorer for størrelsen på disken, der skal tages i betragtning:

  • Hvor mange poster kan jeg gemme i 5 MB PostgreSQL på Heroku?
  • Bruger der ikke brug af NULL i PostgreSQL stadig en NULL bitmap i headeren?
  • Konfiguration af PostgreSQL til læseydelse

Matrixtyper?

Med en array skriver, som du evaluerede, ville du tilføje 24 bytes overhead for typen. Plus, array-elementer optager plads som normalt. Intet at vinde der.



  1. PG::InvalidParameterValue:FEJL:ugyldig værdi for parameteren client_min_messages:panik

  2. SQL:Opdater en række og returner en kolonneværdi med 1 forespørgsel

  3. Hvordan forbinder man Android-app til MySQL-database?

  4. Sådan fungerer Replace() i SQLite