PostgreSQL på en VPS: dimensionér hukommelse og disk

En hurtig PostgreSQL-database er en database, hvor de data, der ofte læses, kan ligge i hukommelsen. Hele dimensioneringen tager udgangspunkt i det: databasens størrelse, den del, der reelt arbejdes med, antallet af forbindelser og derefter disken og dens margin. Denne guide giver dig metoden, startindstillingerne til 4, 8 og 16 GB hukommelse og de forespørgsler, der måler en eksisterende database.

Udgivet den 29. oktober 2026 Af Læsetid: 10 minutter

Alle guider

Det vigtigste

  1. Mål størrelsen på databasen og dens indeks, og derefter den del, der ofte læses: det er den, der skal kunne ligge i hukommelsen.
  2. Udgangspunkt: shared_buffers på 25 % af hukommelsen, effective_cache_size på 75 %, random_page_cost = 1.1 på NVMe-SSD.
  3. Hver forbindelse er en proces: ud over nogle titals aktive forbindelser sætter du PgBouncer foran databasen.
  4. Disk: data og indeks om et år plus mindst 30 % margin. En fuld disk stopper PostgreSQL.
  5. Cache-hitraten skal holde sig over 99 %: under det mangler databasen hukommelse.
  6. Tag backup hver dag med pg_dump, uden for serveren, og gendan regelmæssigt for at kontrollere den.

Tag udgangspunkt i den aktive datamængde

Hukommelsen på en databaseserver fungerer først og fremmest som cache: en side, der læses fra hukommelsen, leveres langt hurtigere end en side, der læses fra disken, selv en NVMe-disk. Spørgsmålet er derfor ikke kun «hvor meget fylder databasen?», men «hvor stor en del læses ofte?». En database på 50 GB, hvor kun de seneste tolv måneder bruges, arbejder måske på 8 GB.

På en eksisterende database giver to forespørgsler den samlede størrelse og de største tabeller, indeks medregnet:

SQL (psql)
SELECT pg_size_pretty(pg_database_size(current_database()));

SELECT relname AS tabel,
       pg_size_pretty(pg_total_relation_size(relid)) AS storrelse_med_indeks
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;

For en kommende database skønner du tabel for tabel: antal forventede rækker om et år × gennemsnitlig rækkestørrelse, og derefter lægger du indeksene til, som ofte fylder 30 til 100 % af dataene. Eksempel: 2 millioner rækker om måneden på 500 byte hver giver 12 GB data om et år og 18 til 24 GB med indeks.

Hukommelsen: startindstillingerne

PostgreSQL holder de læste sider på to niveauer: sin egen cache (shared_buffers) og systemets filcache. Dokumentationen anbefaler at starte med 25 % af hukommelsen til shared_buffers på en dedikeret server og bemærker, at gevinsten bliver sjælden over 40 %: resten kommer systemets cache og sorteringerne til gode.

Parameter4 GB8 GB16 GBRolle
shared_buffers1 GB2 GB4 GBPostgreSQL's egen cache
effective_cache_size3 GB6 GB12 GBDen anslåede samlede cache, som styrer valget af forespørgselsplaner
work_mem8 MB16 MB32 MBHukommelsen til hver sortering eller hashing pr. forbindelse: skal ganges med antallet af samtidige forespørgsler
maintenance_work_mem256 MB512 MB1 GBOprettelse af indeks og VACUUM
random_page_cost1.11.11.1Den anslåede omkostning ved en tilfældig læsning: 4 som standard, langt over den reelle omkostning på NVMe-SSD

Disse værdier forudsætter, at databasen står alene på serveren. Kører applikationen ved siden af, så træk først dens hukommelse fra (processer, cache, kompilering), og anvend procentsatserne på resten: en server med 8 GB, der kører en applikation på 3 GB, indstilles som en database med 5 GB.

postgresql.conf til en server med 8 GB, dedikeret til databasen
shared_buffers = 2GB
effective_cache_size = 6GB
work_mem = 16MB
maintenance_work_mem = 512MB
random_page_cost = 1.1

shared_buffers træder først i kraft, når PostgreSQL genstartes; de andre parametre genindlæses uden afbrydelse med SELECT pg_reload_conf();.

For at vide, om hukommelsen er tilstrækkelig, læser du cache-hitraten. For en forretningsapplikation eller en hjemmeside ligger den over 99 %:

SQL (psql)
SELECT round(100.0 * blks_hit / nullif(blks_hit + blks_read, 0), 2) AS cache_hitrate
FROM pg_stat_database
WHERE datname = current_database();

Forbindelserne: én proces hver

PostgreSQL åbner én proces pr. forbindelse og accepterer 100 som standard (max_connections). Hver proces optager nogle få megabyte i hvile, mere når den sorterer eller hasher data (work_mem, nogle gange flere gange i samme forespørgsel). At hæve max_connections til 500 for at følge med en snakkesalig applikation er at risikere, at serveren løber tør for hukommelse ved første spidsbelastning.

Det rigtige svar er en connection pooler: PgBouncer i transaction-tilstand lader hundredvis af applikationsforbindelser dele nogle titals reelle forbindelser. Frameworks har også deres egen pool (SQLAlchemy, Prisma, HikariCP): indstil dens størrelse efter antallet af vCPU på databaseserveren frem for efter antallet af brugere.

Disken: størrelse, margin og transaktionslog

Disken på en PostgreSQL-server rummer mere end tabellerne:

Reglen: størrelsen om et år plus mindst 30 % margin. Det er ikke luksus: når den disk, der rummer transaktionsloggen, bliver fuld, stopper PostgreSQL for at beskytte sine data. Hold øje med pladsforbruget, og udvid, før det når 80 %.

Hvad ydeevnen angår, venter hver bekræftelse af en transaktion på, at loggen er skrevet til disken: lagerets latenstid bestemmer skrivehastigheden. Det er her, en NVMe-SSD gør forskellen, langt mere end ved læsninger, som hukommelsen allerede leverer.

Processoren: én forespørgsel, én kerne

En PostgreSQL-forespørgsel kører på en enkelt kerne, bortset fra de store læsninger, som motoren paralleliserer. Antallet af vCPU bestemmer derfor antallet af tunge forespørgsler, der behandles samtidig: 2 vCPU er nok til en forretningsapplikation ved lanceringen, 4 til 8 passer til meget belastede databaser og tunge rapporter.

Før du tilføjer vCPU, så find de forespørgsler, der bruger dem. Udvidelsen pg_stat_statements sorterer dem efter samlet tid:

postgresql.conf, derefter genstart
shared_preload_libraries = 'pg_stat_statements'
SQL (psql)
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;

SELECT calls, round(total_exec_time) AS ms_total,
       round(mean_exec_time::numeric, 1) AS ms_gennemsnit, query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;

Samme server som applikationen, eller en separat server?

Ved lanceringen er databasen på samme server som applikationen det rigtige valg: ingen netværkslatens mellem de to, forbindelse via Unix-socket, én server at tage backup af og overvåge. Man skiller dem ad, når de to konkurrerer om ressourcerne: en kompilering eller en trafikspids, der tømmer databasens cache, en database, der har brug for al hukommelsen til sine data, eller forskellige krav til backup.

Sikkerhed og backup

Terminal: komprimeret eksport, derefter gendannelse i en testdatabase
pg_dump -Fc -d min_database -f min_database-$(date +%F).dump
createdb min_database_test
pg_restore -d min_database_test min_database-2026-10-29.dump

En hurtig PostgreSQL-database på den rigtige server

VPS Pro kører på Intel Xeon-processorer, ECC-hukommelse, der retter fejl i realtid, og spejlede NVMe-SSD'er, med hver datablok verificeret med kontrolsum og en krypteret backup hver nat uden for maskinen. Totalsupport er inkluderet: når din database bliver langsom, analyserer vi de langsomme forespørgsler og indeksene og fortæller dig derefter, hvilke indstillinger der giver din applikation dens hastighed tilbage.

Opdag VPS Pro

Ofte stillede spørgsmål

Hvor meget RAM skal PostgreSQL have?

Nok til, at de data, der ofte læses, kan ligge i hukommelsen. Til en forretningsapplikation ved lanceringen er 4 GB nok, database og applikation medregnet. Derefter måler du cache-hitraten: så længe den holder sig over 99 %, er hukommelsen tilstrækkelig.

Hvilken værdi skal shared_buffers have?

25 % af hukommelsen på en server, der er dedikeret til databasen, som PostgreSQL's dokumentation anbefaler: 1 GB på 4 GB, 2 GB på 8 GB, 4 GB på 16 GB. Over 40 % bliver gevinsten sjælden, fordi systemets cache klarer resten.

Hvor mange PostgreSQL-forbindelser kan en VPS klare?

PostgreSQL accepterer 100 som standard, og hver forbindelse er en proces, der bruger hukommelse. I stedet for at hæve det loft sætter du en connection pooler som PgBouncer foran databasen: nogle titals reelle forbindelser betjener så hundredvis af applikationsforbindelser.

Skal databasen og applikationen på hver sin server?

Ikke ved lanceringen: på samme server svarer databasen uden netværkslatens, og det hele tages der backup af i ét. Man skiller dem ad, når den ene generer den anden, for eksempel når en kompilering eller en trafikspids tømmer databasens cache.

Kontakt os