Hoppa till innehåll
Data & AnalysPostgreSQLDatabasoptimeringPrestanda14 min läsning

PostgreSQL prestanda: Optimering för svenska SaaS-bolag

PostgreSQL är ryggraden i många svenska SaaS-bolag – så optimerar du prestanda och får ut maximalt av din databas.

18 augusti 2026Uppdaterad 10:00
3 40026
PostgreSQL prestanda: Optimering för svenska SaaS-bolag
PostgreSQL-prestanda handlar om index, konfiguration och övervakning – en optimerad databas kan vara 100x snabbare än en ooptimerad.Photo: Unsplash

PostgreSQL är den mest använda databasen för moderna SaaS-applikationer. Denna guide täcker query-optimering, indexeringsstrategier, EXPLAIN ANALYZE, connection pooling, vacuum-tuning, konfiguration, partitionering, replikering och övervakning för svenska SaaS-bolag.

PostgreSQL är en av världens mest kraftfulla open source-databaser och ryggraden i otaliga SaaS-applikationer – från svenska startups till globala enterprise-system. Men en PostgreSQL-databas är bara så bra som dess konfiguration och frågedesign. Jag har sett enkla SaaS-applikationer bli 50–100x snabbare efter rätt indexering och konfigurationstuning.

Den här guiden ger dig en komplett genomgång av PostgreSQL-prestandaoptimering – från grundläggande indexering till avancerad VACUUM-tuning och connection pooling. Jag har arbetat med PostgreSQL i över ett decennium för allt från enkla CMS till högpresterande SaaS-plattformar med miljontals användare.

Query-optimering – grunden för prestanda

De flesta PostgreSQL-prestandaproblem orsakas av ineffektiva frågor – inte av databaskonfigurationen. En fråga som är rätt skriven och har rätt index kan vara 1000x snabbare än samma fråga utan rätt index eller med en ineffektiv JOIN-ordning. Börja alltid med att analysera dina långsamma frågor före du justerar konfigurationsparametrar.

Använd `EXPLAIN ANALYZE` före varje frågeoptimering. EXPLAIN visar frågeplanen utan att köra den – planerarens uppskattning. EXPLAIN ANALYZE kör frågan och visar faktisk exekveringstid, antal rader, och varje stegs faktiska kostnad. Leta efter: Sequential Scan (bör vara index scan), Nested Loop med många iterationer, och Hash Join som byter ordning på tabeller.

Verktyg för query-analys: pg_stat_statements (inbyggd extension – loggar alla frågor, deras totala tid, antal anrop, och genomsnittlig tid), och externa verktyg som pgBadger (logganalys), PgAnalyze (query-analyzer) och Supabase Database Adviser. Installera pg_stat_statements i postgresql.conf och du har omedelbar insyn i dina tyngsta frågor.

Indexeringsstrategier – rätt index för rätt fråga

Index är det mest effektiva sättet att snabba upp PostgreSQL-frågor. Standard B-tree-index är bra för de flesta fall: exakta matchningar, range-queries, ORDER BY, och LIKE-frågor (med prefix-matchning). Skapa index på kolumner som används i WHERE, JOIN och ORDER BY – men överindexera inte, varje index lägger till overhead på INSERT/UPDATE/DELETE.

Specialiserade index: GIN (Generalized Inverted Index) – bra för JSONB, arrayer, och fulltextsökning (tsvector). BRIN (Block Range Index) – bra för stora tabeller med naturligt sorterad data (tidsstämplar, loggar). Hash-index – för exakta matchningar, snabbare än B-tree för enkla lookups (men mindre flexibla). GiST (Generalized Search Tree) – för geospatial data (PostGIS) och fulltextsökning.

Skapa sammansatta index (composite indexes) för frågor som filtrerar på flera kolumner: `CREATE INDEX idx_orders_user_date ON orders(user_id, created_at DESC);`. Kolumnordningen i indexet är viktig – sätt kolumner med hög selektivitet först. Använd "Covering indexes" med INCLUDE för att göra index-only scans: `CREATE INDEX idx_orders_user_id ON user_orders(user_id) INCLUDE (total, status);` – detta undviker heap-access helt.

EXPLAIN ANALYZE – läsa frågeplanen

Lär dig läsa EXPLAIN ANALYZE – det är den viktigaste färdigheten för PostgreSQL-prestanda. En typisk frågeplan visar noder som: Seq Scan (scannar hela tabellen – dyrt, bör undvikas på stora tabeller), Index Scan (använder index för att hitta rader – bra, för exakta matchningar), Index Only Scan (all data finns i indexet – bäst, ingen heap-access), Bitmap Index Scan + Bitmap Heap Scan (kombinerar flera index – bra för komplexa filter), och Nested Loop / Hash Join / Merge Join (olika JOIN-strategier).

Prestandaindikatorer i EXPLAIN ANALYZE: "rows" (uppskattat vs faktiskt – stor diskrepans indikerar inaktuell statistik), "cost" (relativ kostnad – inte tid), "actual time" (faktisk tid i ms), "buffers" (antal lästa sidor – viktig indikator på I/O-belastning), och "loops" (för Nested Loop – varje iteration är en index-lookup, kan bli dyr vid många iterationer).

Kör `ANALYZE` eller `VACUUM ANALYZE` om statistiken är inaktuell (stor diskrepans mellan planerarens uppskattning och faktiskt antal rader). Använd `random_page_cost`-konfiguration för att justera planerarens antaganden – för SSD-diskar (0.1–0.5) kontra HDD (4.0) eller cloud-lagring (1.0–2.0).

Connection pooling – hantera många anslutningar

PostgreSQL är process-baserad – varje anslutning skapar en OS-process, inte en tråd. När antalet anslutningar överstiger 100–200, börjar prestandan försämras dramatiskt på grund av context switching, minne och lås-konflikter. Connection pooling löser detta genom att multiplexera många klientanslutningar över ett fåtal databasanslutningar.

PgBouncer är den mest använda connection poolern för PostgreSQL. Den körs som en lätt proxyserver som klienterna ansluter till i stället för direkt till databasen. PgBouncer har flera pooling-lägen: Session (pool per session – fungerar med alla applikationer), Transaction (pool per transaktion – bäst för de flesta), och Statement (pool per statement – för enkla frågor, sällan användbart).

PgCat är en nyare connection pooler (2024+) med stöd för sharding, load balancing, och failover. Supabase använder PgBouncer som standard för alla projekt. Rekommenderad konfiguration: 25–50 anslutningar i poolen för de flesta applikationer. Övervaka anslutningsantal med pg_stat_activity och justera poolstorleken.

VACUUM-tuning – förhindra bloat och prestandaförsämring

PostgreSQL använder MVCC (Multi-Version Concurrency Control) – när en rad uppdateras skapas en ny version medan den gamla versionen markeras som död. VACUUM rensar bort döda rader och återanvänder utrymmet. Utan regelbunden VACUUM växer tabellerna (bloat) och prestandan försämras – Sequential Scans blir långsammare och index blir mindre effektiva.

Autovacuum är aktiverat som standard men kan behöva justeras för dina arbetsbelastningar. Viktiga parametrar: `autovacuum_vacuum_threshold` (50 rader som standard – kan vara för lågt för stora tabeller), `autovacuum_vacuum_scale_factor` (0.2 som standard – 20% av tabellen måste ändras före VACUUM). För stora tabeller (miljoner rader), sänk scale_factor till 0.01 och öka threshold.

Övervaka bloat med pg_stat_user_tables (n_dead_tup, n_live_tup, last_autovacuum). Använd pg_repack extension för att rensa bloat utan nedtid. För SaaS-applikationer med höga INSERT/UPDATE-volymer: konfigurera aggresiv autovacuum, använd fillfactor < 100 (t.ex. fillfactor=90 för tabeller med frekventa UPDATE), och övervaka tabellstorlek över tid.

Konfiguration – postgresql.conf-inställningar

PostgreSQL-standardkonfigurationen är mycket konservativ – avsedd att fungera på en Raspberry Pi. Din SaaS-applikation behöver helt andra inställningar. Börja med `shared_buffers` – standard är 128 MB, bör vara ~25% av RAM (för en server med 16 GB RAM: 4 GB). `effective_cache_size` – uppskattning av OS-cache: ~75% av RAM.

Andra viktiga inställningar: `work_mem` (per query, standard 4 MB – öka till 16–64 MB för bättre sort/hash-prestanda), `maintenance_work_mem` (per VACUUM/INDEX, standard 64 MB – öka till 1 GB för snabbare indexbyggen), `random_page_cost` (SSD: 1.1, cloud: 1.0–1.5), `effective_io_concurrency` (SSD: 200–300, NVMe: 500+), och `max_worker_processes` + `max_parallel_workers` för parallellfrågor.

Använd pgtune (https://pgtune.leopard.in.ua) eller PGConfig för att generera en baskonfiguration baserat på ditt systems RAM, CPU och disktyp. Justera och övervaka iterativt – ändra en parameter i taget och mät effekten på dina viktigaste frågor. Använd `SHOW ALL` för att se aktuella inställningar och `pg_settings` för att se vilka som är standard vs anpassade.

Partitionering – hantera stora datamängder

Tabellpartitionering delar upp en stor tabell i mindre, mer hanterbara delar baserat på en nyckel (t.ex. datum, region, kund-ID). PostgreSQL stöder range partition, list partition och hash partition (sedan version 10, med förbättringar i version 11–16). Partionering förbättrar query-prestanda (partition pruning – endast relevanta partitioner skannas) och underhåll (VACUUM en partition i taget).

Range partitionering är vanligast för SaaS-applikationer: `PARTITION BY RANGE (created_at)` med månads- eller kvartalspartitioner. Äldre partitioner kan arkiveras (detach + move to cold storage) eller komprimeras. List partitionering för kategorier: `PARTITION BY LIST (status)`. Hash partitionering för load balancing: `PARTITION BY HASH (customer_id)` med 4–16 partitioner.

För att partitionera en befintlig tabell: skapa en ny partitionerad tabell, använd pg_partman extension för automatisk hantering av partitioner (skapa nya, detachera gamla), och migrera data via INSERT INTO ... SELECT eller ett skript. För SaaS-applikationer med logg-historik eller tidsbaserad data rekommenderas partitionering starkt – förbättrar både prestanda och underhåll.

Replikering – läs-skalning och hög tillgänglighet

PostgreSQL streaming replication skickar WAL (Write-Ahead Log) från primär till en eller flera repliker. Repliker kan vara: Hot Standby (läsbara, asynkrona eller synkrona), eller Cascading Replica (replik från en annan replik). Använd streaming replication för: läs-skalning (skicka skrivskyddade frågor till repliker), hög tillgänglighet (failover vid primär-fel), och backup (ta backup från replik).

Patroni är standardverktyget för PostgreSQL high availability – hanterar automatisk failover, replication, och konsistens. Kombinera med etcd eller Consul för cluster-koordinering. Patroni används i produktion av många svenska SaaS-bolag. För enklare setup: repmgr (Replication Manager) är lättare att konfigurera men har färre funktioner.

Använd load balancers (pgpool-II, HAProxy) för att dirigera skrivningar till primär och läsningar till repliker. Övervaka replikeringsfördröjning (lag) med pg_stat_replication – för hög fördröjning kan leda till datakonsistensproblem. Använd synchronous replication för kritiska skrivningar (bekräfta att data skrivits till minst en replik före commit).

Övervakning och alerting

PostgreSQL-övervakning är avgörande för att upptäcka prestandaproblem innan de påverkar användare. Använd pg_stat_statements för query-analys, pg_stat_activity för aktiva anslutningar, pg_stat_user_tables för bloat-övervakning, pg_stat_replication för replikeringsfördröjning, och pg_stat_bgwriter för checkpoint-aktivitet.

Övervakningsverktyg: pgAdmin (dashboard), Datadog (PostgreSQL-integration), Grafana med postgres_exporter (Prometheus), och lokala verktyg som check_pgactivity (Nagios/Icinga). Konfigurera alerting för: connections > 80% av max_connections, replication lag > 60 sekunder, antal långsamma queries > tröskelvärde, tabellbloat > 20%, och autovacuum som inte hinner ikapp.

Använd PostgreSQL-logging med log_line_prefix som innehåller tidsstämpel, PID, användare och databas. Analysera loggar med pgBadger för att generera detaljerade rapporter om query-prestanda, fel, och anslutningsmönster. Schemalägg logganalys dagligen och skicka sammanfattning till teamet.

Sammanfattning: PostgreSQL best practices för SaaS

  1. Börja med frågeoptimering – analysera långsamma queries med EXPLAIN ANALYZE och pg_stat_statements.
  2. Skapa rätt index – B-tree för de flesta frågor, GIN för JSONB/fulltext, BRIN för tidsseriedata.
  3. Använd connection pooling (PgBouncer) – sätt poolstorlek till 25–50 anslutningar.
  4. Justera autovacuum för dina arbetsbelastningar – övervaka bloat kvartalsvis.
  5. Använd pgtune för baseline-konfiguration – shared_buffers, work_mem, effective_cache_size.
  6. Partitionera stora tabeller – förbättrar prestanda och underhåll avsevärt.
  7. Använd streaming replication för läs-skalning och hög tillgänglighet (Patroni).
  8. Övervaka med postgres_exporter + Grafana och alerta på kritiska tröskelvärden.
  9. Använd pg_cron eller pg_timetable för schemalagda underhållsjobb.
  10. Använd en cache-lager (Redis) framför PostgreSQL för lästunga workloads.

PostgreSQL är en extremt kraftfull databas när den är rätt konfigurerad. Investera tid i indexering, konfiguration och övervakning – det betalar sig många gånger om i prestanda, driftsäkerhet och lägre kostnader.

Vill du ha hjälp med PostgreSQL-prestanda?

Jag hjälper SaaS-bolag att optimera sina PostgreSQL-databaser. Läs mer om data- och analystjänster eller boka ett samtal.

Jag har sett enkla SaaS-applikationer bli 50–100x snabbare efter rätt indexering och konfiguration – PostgreSQL är kraftfullt men kräver rätt inställningar.

- Simon Axelsson

Vanliga frågor

Hur vet jag vilka frågor som är långsamma i PostgreSQL?
Installera pg_stat_statements extension och querya vyer: SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10. Det visar dina tyngsta frågor med total tid, antal anrop, genomsnittlig tid, och buffertläsningar. Använd också slow query logging: log_min_duration_statement = 1000 (loggar frågor som tar > 1 sekund).
Vad är skillnaden mellan B-tree, GIN och BRIN index?
B-tree (standard) – bäst för exakta matchningar, range-queries, ORDER BY och prefix-LIKE. GIN – bäst för JSONB, arrayer och fulltextsökning (tsvector). BRIN – bäst för stora tabeller med naturligt sorterad data (tidsstämplar) – mycket mindre än B-tree men kräver att data är fysiskt sorterad. Välj index baserat på datatyp och frågemönster.
Hur mycket RAM bör PostgreSQL ha?
shared_buffers: 25% av RAM (16 GB RAM -> 4 GB). effective_cache_size: 75% av RAM (16 GB -> 12 GB). work_mem: 16–64 MB per query. maintenance_work_mem: 1 GB. Totalt: PostgreSQL använder shared_buffers + connections × work_mem + maintenance_work_mem. För en standard SaaS-server med 16 GB RAM: ca 6–8 GB dedikerat till PostgreSQL.
Vad är connection pooling och varför behöver jag det?
PostgreSQL är process-baserad – varje anslutning kräver en OS-process (10+ MB per anslutning). Över 100–200 anslutningar försämras prestandan dramatiskt. PgBouncer multiplexerar många klientanslutningar över ett fåtal databasanslutningar (25–50). Utan connection pooling kan din SaaS-applikation få anslutningsproblem och hög CPU-belastning vid skalning.
När ska jag partitionera en PostgreSQL-tabell?
Partitionera tabeller som är > 100 GB eller har > 100 miljoner rader, eller där äldre data regelbundet arkiveras/raderas. Range partitionering med månadspartitioner är vanligast för SaaS-applikationer. Partionering förbättrar query-prestanda (partition pruning), VACUUM-hastighet (endast en partition i taget), och underhåll (detach + drop gamla partitioner).

Om författaren

Simon Axelsson
Simon AxelssonIT-konsult & teknisk rådgivare

Simon Axelsson är senior IT-konsult och grundare av SIAX Technology AB. Han hjälper nordiska företag med molninfrastruktur, dataplattformar och AI-automation.

Fler artiklar av Simon