Det korta svaret
Välj PostgreSQL för en ny app som du skriver eller väljer själv: i våra tester var den långsammare på läsning men lika snabb på skrivning, använde minst minne i vila, återställde en dump fem till åtta gånger snabbare och hade det som de andra saknar, som migreringar som rullas tillbaka helt, index på JSON, fulltextsökning på svenska och tillägg som pgvector. Välj MySQL eller MariaDB när appen förväntar sig dem, som WordPress och de flesta PHP-appar gör. Vilken av de två det ska vara går vi igenom i MySQL eller MariaDB?.
Det här testade vi
Vi installerade alla tre på samma nya Melonslab VC-P Titanium (4 vCPU, 16 GB) med Debian 13 och följde våra guider Kör en egen PostgreSQL-databasserver, Kör en MySQL-databasserver och Kör en MariaDB-databasserver steg för steg, med den privata WireGuard-varianten och de inställningar varje guide ger för en server med 8 GB. PostgreSQL körs från Debians paket som en systemtjänst. MySQL och MariaDB körs som var sin container i Podman utan root, under en egen användare.
MySQL och MariaDB använder båda port 3306, och deras guider säger att du ska köra en av dem per server. För att köra dem sida vid sida gav vi MariaDB port 3307 med en extra fil bredvid inställningarna från guiden, ~/mariadb/conf.d/port.cnf:
[mariadb]
port = 3307
och öppnade 3307 i tunneln i stället för 3306 (ufw allow in on wg0 to any port 3307 proto tcp). Apparna ansluter då till port 3307. Allt annat, också hälsokontrollen, fungerade som förut.
Sedan körde vi samma tester på var och en, en databas i taget med de andra två stoppade, och med samma gräns på 6 GB minne för alla tre, satt med systemd:
- sysbench
oltp_read_onlyocholtp_read_writepå åtta tabeller med en miljon rader (omkring 2 GB), med 1, 8 och 32 klienter i 60 sekunder, varje körning två gånger, från servern själv; - pgbench på PostgreSQL som en kontroll;
- en CSV-fil med fem miljoner beställningar (519 MB) som vi importerade, indexerade, dumpade och återställde med kommandona från varje guides säkerhetskopiering, och en fysisk säkerhetskopia med var och ens eget verktyg;
- samma SQL för migreringar, villkor, JSON, fulltextsökning och vektorer i alla tre;
- 90 anslutningar i vila till var och en, och 500 till PostgreSQL via PgBouncer.
Siffrorna
| PostgreSQL 18.6 | MySQL 9.7.2 | MariaDB 12.3.3 | |
|---|---|---|---|
| Hur den körs | Debians paket, systemtjänst | 1 container | 1 container |
| Steg i vår guide | 8 | 11 | 11 |
| Installation och första start | 39 sekunder | 50 sekunder | 26 sekunder |
| Minne i vila efter omstart | omkring 100 MB | 820 MB | 1,2 GB |
| Disk efter installationen | 0,3 GB paket, 47 MB data | avbild på 952 MB, 1,2 GB data | avbild på 346 MB, 1,1 GB data |
| Läsning, 8 klienter (transaktioner/s) | 1 374 | 1 583 | 1 531 |
| Läsning och skrivning, 8 klienter (transaktioner/s) | 767 | 317 | 787 |
| Import av 5 miljoner rader, sedan två index | 28 + 16 sekunder | 56 + 22 sekunder | 38 + 20 sekunder |
| Nattlig dump, som i guiden | 21 sekunder, 118 MB | 21 sekunder, 122 MB | 23 sekunder, 122 MB |
| Återställning av dumpen | 28 sekunder | 220 sekunder | 140 sekunder |
| Minne per anslutning i vila | omkring 1,9 MB | omkring 0,5 MB | omkring 0,1 MB |
| Licens | PostgreSQL Licence | GPL 2, eller kommersiell från Oracle | GPL 2 |
Minnet är vad varje tjänsts cgroup använde några minuter efter en omstart, utan några anslutningar. För containrarna visade podman stats samma sak. Datan på disken efter installationen är mest den redo-logg på 1 GB som guiderna för MySQL och MariaDB ställer in. Installationstiden är hur lång tid kommandona tog på vår server, med nedladdning av avbilder, inte hur lång tid det tar att läsa guiden.
Hastighet
Siffrorna är transaktioner per sekund, medelvärdet av två körningar. En transaktion i sysbench med bara läsning är 14 frågor, en med läsning och skrivning 18.
| Klienter | PostgreSQL | MySQL | MariaDB |
|---|---|---|---|
| Läsning, 1 | 292 | 396 | 357 |
| Läsning, 8 | 1 374 | 1 583 | 1 531 |
| Läsning, 32 | 1 252 | 1 470 | 1 477 |
| Läsning och skrivning, 1 | 116 | 91 | 137 |
| Läsning och skrivning, 8 | 767 | 317 | 787 |
| Läsning och skrivning, 32 | 754 | 598 | 765 |
På läsning var MySQL och MariaDB 10 till 35 % snabbare än PostgreSQL. På skrivning låg PostgreSQL och MariaDB lika, och MySQL låg långt efter med 8 klienter. Skillnaden är MySQLs binärlogg: den är på från början och skrivs till disk vid varje commit, som underlag för replikering och för att återställa till en viss tidpunkt. MariaDB har den avstängd från början, och PostgreSQL har en enda logg, sin WAL, för båda. När vi stängde av binärloggen för ett test kom MySQL upp i 569 transaktioner per sekund med 8 klienter och 798 med 32, nära de andra. Låt den vara på: utan den kan du inte återställa till en viss tidpunkt.
MariaDB fick göra om några transaktioner efter låsningar (deadlocks) i testet med skrivning, upp till 111 under en körning på 60 sekunder, de andra nästan inga. sysbench gör om dem själv, som en app ska göra.
pgbench, PostgreSQLs eget verktyg, gav 1 483 och 2 199 transaktioner per sekund med skrivning och omkring 27 000 med bara läsning, med 8 och 32 klienter. Dess transaktioner är enklare än sysbench, så siffrorna går bara att jämföra med varandra. Datan fick plats i minnet i alla tester, som den brukar för en liten app. För en databas som är större än minnet avgör disken mer än databasen.
Ingen av de tre är så snabb eller långsam att det här ska avgöra ditt val. Kör din egen apps frågor om hastigheten spelar roll.
Import, dumpar och återställning
Samma CSV-fil på 519 MB med fem miljoner beställningar gick in i samma tabell i alla tre, med COPY i PostgreSQL och LOAD DATA INFILE i de andra två, och sedan två index:
| PostgreSQL | MySQL | MariaDB | |
|---|---|---|---|
| Import | 28 s | 56 s | 38 s |
| Två index | 16 s | 22 s | 20 s |
| Tabellen med index | 847 MB | 733 MB | 716 MB |
Dump (pg_dump / mysqldump / mariadb-dump) | 21 s, 118 MB | 21 s, 122 MB | 23 s, 122 MB |
| Återställning av dumpen | 28 s | 220 s | 140 s |
Fysisk säkerhetskopia (pg_basebackup / XtraBackup / mariadb-backup) | 8 s | 68 s | 11 s |
Alla tre fick tillbaka alla fem miljoner rader. Dumparna var lika stora och tog lika lång tid, men en dump från MySQL eller MariaDB är en fil med INSERT-satser som måste köras igen, medan pg_dump i sitt eget format laddar med COPY och bygger indexen efteråt. För en stor databas är det skillnaden mellan minuter och en timme när du behöver få tillbaka den. Därför lägger våra guider för MySQL och MariaDB till en fysisk säkerhetskopia. MySQLs tog längst tid, och den tiden räknar med att XtraBackups egen container på 1,6 GB ska starta.
PostgreSQL tog 15 till 18 % mer plats för tabellen. Dess rader bär mer information för hanteringen, och VACUUM tar tillbaka platsen från raderade och ändrade rader i bakgrunden.
Migreringar och regler för data
Migreringar som misslyckas halvvägs. Vi körde samma migrering i en transaktion i alla tre: lägg till en kolumn, skapa en tabell och lägg sedan till ett villkor som befintlig data bryter mot. I PostgreSQL rullade felet tillbaka allt, och tabellen såg ut som förut. I MySQL och MariaDB fanns kolumnen och den nya tabellen kvar efter ROLLBACK: varje ALTER eller CREATE gör en commit av sig själv, och varje sats är atomär, men en migrering med flera satser är det inte. När en driftsättning misslyckas halvvägs lämnar PostgreSQL dig där du var. De andra två lämnar dig att städa för hand.
Villkor. Alla tre vägrade ett negativt pris mot CHECK (price >= 0), och alla tre vägrade 'abc' i en sifferkolumn och sju bokstäver i en varchar(5). MySQL och MariaDB har gjort så som standard i flera år, med strict SQL mode. Men läget är en inställning som en app kan ändra, och en del äldre PHP-appar gör det. Med sql_mode='' sparade båda 0 och toolo med bara en varning. PostgreSQL har inget sådant läge.
De skiljer sig också i misstag som inte är fel i MySQL och MariaDB: SELECT 1/0 gav NULL i båda, och datumet 2026-02-30 blev NULL. PostgreSQL stoppade med division by zero och date/time field value out of range.
Stora och små bokstäver, och accenter. Som standard jämför MySQL och MariaDB text utan att bry sig om stora och små bokstäver eller accenter: 'Anna' = 'anna' och 'Åsa' = 'Asa' var båda sanna. En unik kolumn för e-post behandlar då också Anna@example.com och anna@example.com som samma, vilket ofta är vad du vill, och en sökning på Asa hittar Åsa, vilket en svensk app kanske inte vill. PostgreSQL såg båda paren som olika. För text där stora och små bokstäver inte ska spela roll i PostgreSQL finns tillägget citext eller en ICU-sortering som inte skiljer på dem. MySQL och MariaDB har svenska sorteringar som håller isär Å, Ä och Ö.
Tabellnamn fungerar tvärtom. I PostgreSQL skapar CREATE TABLE Customers tabellen customers, och båda stavningarna hittar den. I MySQL och MariaDB på Linux skiljer tabellnamn på stora och små bokstäver: SELECT FROM customers stoppade med Table 'demo.customers' doesn't exist. En app som utvecklats på Windows eller macOS kan snubbla på det på en Linuxserver.
Tecken genom containern. Kommandot mysql inne i MySQL-containern använde latin1 när vi skickade in SQL till det, och sparade Åsa som Ã…sa. MariaDBs använde utf8mb4. Dumpar påverkas inte, eftersom de anger sin egen teckenuppsättning, men lägg till --default-character-set=utf8mb4 när du skriver eller skickar in text med å, ä eller ö i MySQL på det sättet.
JSON
Alla tre sparar JSON och vägrade ogiltig JSON. De indexerar det på olika sätt.
PostgreSQLs jsonb tar ett GIN-index på hela kolumnen, och det indexet svarar sedan på frågor om vilken nyckel som helst:
CREATE INDEX events_doc ON events USING gin (doc jsonb_path_ops);
SELECT count(*) FROM events WHERE doc @> '{"type": "buy", "user": 42}';
SELECT count(*) FROM events WHERE doc @> '{"tags": ["t7"]}';
Med 100 000 händelser visade EXPLAIN Bitmap Index Scan on events_doc för båda frågorna.
MySQL och MariaDB indexerar en nyckel i taget, genom en genererad kolumn:
ALTER TABLE events ADD COLUMN type varchar(10) AS (JSON_VALUE(doc, '$.type')) VIRTUAL,
ADD COLUMN user int AS (JSON_VALUE(doc, '$.user')) VIRTUAL, ADD INDEX type_user (type, user);
SELECT count(*) FROM events WHERE type = 'buy' AND user = 42;
Båda använde indexet för den frågan, men en JSON_CONTAINS på samma nycklar läste ändå hela tabellen. MySQL kan också indexera värdena i en lista, med ett multi-valued index och MEMBER OF, som den använde för taggarna. MariaDB har inget multi-valued index och inte förkortningen ->>, och dess JSON är en LONGTEXT med en kontroll av att innehållet är giltigt: dokumenten sparas som text och tolkas vid varje fråga, där PostgreSQL och MySQL sparar ett binärt format.
Om din app sparar flexibel data i JSON och söker i den på sätt du inte vet än, passar PostgreSQL bäst.
Fulltextsökning
Alla tre har index för fulltextsökning. Vi sökte i sex korta texter på svenska och engelska:
| Sökning | PostgreSQL (to_tsquery) | MySQL och MariaDB (MATCH ... AGAINST) |
|---|---|---|
hund | Hundarna springer i parken, En hund i stan, Hundens koppel | En hund i stan |
dog | The dogs are running, A dog sleeps | A dog sleeps |
hund* i boolean mode | alla tre svenska texterna |
PostgreSQL tar fram ordstammen på 29 språk, svenska också, och rangordnar träffarna. MySQL och MariaDB matchar hela ord, så hund hittar inte hundarna. Ett jokertecken hjälper för ändelser, men inte för andra böjningar. För en sökruta på en liten webbplats duger alla tre. För sökning på svenska som hittar det folk menar klarar PostgreSQL det utan något extra program.
SQL-funktioner
Det som saknades för tio år sedan finns nu. En rekursiv WITH-fråga med SUM() OVER och ROW_NUMBER() OVER gick likadant i alla tre och gav samma resultat, och alla tre hade INTERSECT och CHECK-villkor. Resten skilde sig:
| Funktion | PostgreSQL | MySQL | MariaDB |
|---|---|---|---|
INSERT ... RETURNING | ja | nej | ja |
FULL OUTER JOIN | ja | nej | nej |
LATERAL | ja | ja | nej |
MERGE | ja | nej | nej |
count(*) FILTER (WHERE ...) | ja | nej | nej |
| Sekvenser | ja | nej | ja |
| Listor (arrays) som kolumntyp | ja | nej | nej |
Det finns en väg runt varje "nej". Tillsammans är de skälet till att ORM:er och query builders ofta stöder fler av sina funktioner på PostgreSQL.
Tillägg och vektorer
PostgreSQL går att bygga ut med nya typer, index och funktioner, paketerade i samma arkiv som PostgreSQL själv. Två av dem är skäl till att folk väljer PostgreSQL: PostGIS för kartor och geodata, och pgvector för likhetssökning på AI-embeddings. Vi provade pgvector:
apt install postgresql-18-pgvector
CREATE EXTENSION vector;
CREATE TABLE items(id bigserial PRIMARY KEY, embedding vector(3));
CREATE INDEX items_hnsw ON items USING hnsw (embedding vector_l2_ops);
SELECT id FROM items ORDER BY embedding <-> '[0.5,0.5,0.5]' LIMIT 5;
pgvector 0.8.7 byggde indexet för 100 000 vektorer på 24 sekunder, och EXPLAIN visade Index Scan using items_hnsw. Våra testvektorer hade 3 dimensioner. Riktiga embeddings har hundratals, så räkna med mer minne och disk.
MariaDB har vektorer inbyggt sedan 11.7: typen VECTOR, VECTOR INDEX och VEC_DISTANCE_EUCLIDEAN(), och EXPLAIN visade att indexet användes. MySQL 9.7 har typen VECTOR, men inget index för vektorer, och DISTANCE() stoppade med FUNCTION demo.DISTANCE does not exist: enligt Oracles dokumentation finns den bara i MySQL HeatWave i Oracles moln och i MySQL AI, inte i Community Server.
MySQL och MariaDB har typer och funktioner för geodata inbyggda, utan PostGIS, vilket räcker för avstånd och ytor i många appar. PostGIS går mycket längre.
Anslutningar
PostgreSQL startar en process för varje anslutning, MySQL och MariaDB en tråd. Med 90 anslutningar i vila, efter en fråga var, använde PostgreSQL omkring 170 MB mer, MySQL 45 MB och MariaDB 12 MB.
PostgreSQL-guiden behåller standardvärdet max_connections = 100, och den 98:e anslutningen nekades med remaining connection slots are reserved for roles with the SUPERUSER attribute. En app med många arbetsprocesser, eller många appar mot samma databasserver, behöver en connection pooler. Vi satte PgBouncer 1.26 från Debian framför, i transaction mode med 20 anslutningar till PostgreSQL: 500 klienter från pgbench gick igenom den i 30 sekunder med 6 907 transaktioner per sekund, utan fel. Men en pooler är ett steg till: med 32 klienter och bara läsning gav PgBouncer 9 375 transaktioner per sekund mot 18 616 direkt. Använd den när du behöver fler anslutningar, inte som standard. Många ramverk har en egen pool, och den räcker ofta.
Guiderna för MySQL och MariaDB tillåter 200 anslutningar, och deras trådar är billiga, så de flesta appar behöver aldrig en pooler för dem.
Resurser
I vila använde PostgreSQL omkring 100 MB. Den läser genom systemets filcache, så dess guide ger den en fjärdedel av minnet som egen cache och låter resten av minnet fungera som cache också. MySQL och MariaDB har en egen cache, 4 GB i deras guider, och MariaDB fyllde mer av den när den startade: 820 MB och 1,2 GB efter en omstart. I slutet av testerna använde MySQL 5,9 GB av sina 6 GB, hälften av det sin egen cache, PostgreSQL 5,3 GB, nästan allt filcache som systemet kan ta tillbaka, och MariaDB 2,8 GB.
På disken tog PostgreSQLs paket omkring 0,3 GB, det mesta LLVM för dess frågekompilator. MySQLs avbild var 952 MB, MariaDBs 346 MB. Båda startar med en redo-logg på 1 GB. Efter alla våra tester använde PostgreSQL och MariaDB 2,1 GB data var, och MySQL 4,5 GB, varav 2,5 GB var binärlogg från testerna. Dess guide sparar sju dagar av den, så räkna med disk för en veckas ändringar.
Uppdateringar, säkerhetskopior och replikering
Uppdateringar. PostgreSQL-guiden installerar nya minor-versioner från PostgreSQLs arkiv med unattended-upgrades. Containrarna för MySQL och MariaDB uppdateras med podman auto-update. Alla tre startar om under några sekunder. En ny huvudversion av PostgreSQL kommer en gång om året och får stöd i fem år, och guiden flyttar datan med pg_upgradecluster. MySQL har en LTS-version ungefär vartannat år, MariaDB en långtidsversion varje år med tre års stöd, och båda uppgraderar sin data när den nya versionen startar.
Säkerhetskopior. Alla tre guiderna dumpar varje databas varje natt med en timer och återställer den i testet. Skillnaden är vad du kan göra utöver det:
- PostgreSQLs
pg_basebackupkopierade hela klustret, 946 MB, på 8 sekunder, utan något extra paket. För att kunna återställa till en viss tidpunkt behövs arkivering av WAL och ett verktyg som pgBackRest, som guiden inte tar upp. - MySQL har binärloggen på, med GTID, så ändringarna sedan senaste säkerhetskopian finns redan på disk, och
mysqlbinlogkan spela upp dem fram till en viss tidpunkt. För fysiska säkerhetskopior behövs Percona XtraBackup, som laddas ner separat. - MariaDB har
mariadb-backupi samma avbild, och det tog 11 sekunder. Binärloggen är avstängd från början, så för att kunna återställa till en viss tidpunkt måste du först slå pålog_bin.
Replikering. Alla tre kan hålla en kopia av databasen på en andra server. PostgreSQLs WAL är redo för det från början (wal_level = replica, 10 WAL senders), och en replika startar från en pg_basebackup. MySQL och MariaDB replikerar från binärloggen, och MariaDB har dessutom Galera för ett kluster där varje nod tar emot skrivningar. Vi satte inte upp någon replika i det här testet.
Vilka appar som förväntar sig vad
Många appar bestämmer åt dig. Vi kontrollerade deras egna sidor den 14 oktober 2026:
- WordPress kräver MySQL 8.0 eller senare, eller MariaDB 10.11 eller senare, och nämner inte PostgreSQL. De flesta PHP-appar är likadana, och det gäller några av apparna i våra guider också: BookStack, Kimai, Nextcloud, Passbolt och ERPNext kör alla på MariaDB här.
- Django 6.1 stöder PostgreSQL 15+, MariaDB 10.11+ och MySQL 8.4+, och Rails har adaptrar för alla tre, så en app som du skriver kan använda vilken som helst av dem. Båda har funktioner som bara fungerar på PostgreSQL, som Djangos
ArrayFieldoch fulltextsökning. - De flesta nyare appar som du kör själv väljer PostgreSQL: 16 av app-guiderna här använder den, bland dem Immich, Mattermost, Outline, Paperless-ngx, n8n och Authentik.
Om appen stöder flera, använd den som står först i dess dokumentation. Det är den som utvecklarna testar mest.
Licens och kostnad
Vi kontrollerade projektens egna sidor den 14 oktober 2026.
- PostgreSQL är öppen källkod under PostgreSQL Licence, en kort licens som liknar BSD och MIT: du får använda, ändra och sälja den, också i dina egna produkter, så länge du behåller upphovsrättsnotisen. Den görs av PostgreSQL Global Development Group, ett gemensamt projekt som inget företag äger.
- MySQL Community Server är öppen källkod under GPL version 2 och ägs av Oracle i USA. Oracle säljer en kommersiell licens till företag som levererar MySQL inuti en produkt som de inte vill ge ut under GPL, och MySQL Enterprise Edition med extra verktyg och support. Att köra den som databas för din egen app kräver ingetdera. Vissa funktioner, som
DISTANCE()för vektorer, finns bara i Oracles molntjänst. - MariaDB är öppen källkod under GPL version 2, och dess klientbibliotek under LGPL. Den utvecklas av MariaDB plc i USA och den ideella MariaDB Foundation. MariaDB plc säljer MariaDB Enterprise Server med support till prenumeranter.
Alla tre är gratis att köra själv. GPL spelar bara roll om du distribuerar själva databasen med din produkt. En app som ansluter till den över nätverket påverkas inte.
Vilken ska du välja
PostgreSQL passar en ny app, eller vilken app som helst som stöder den väl: migreringar som rullas tillbaka helt, strikta regler för data som ingen inställning stänger av, JSON som du kan indexera som den är, fulltextsökning på svenska och tillägg som pgvector och PostGIS. Den använde minst minne i vila och återställde en dump fem till åtta gånger snabbare. Dess svagheter är långsammare läsning i vårt test, en process per anslutning, så att appar med mycket trafik behöver en pooler som PgBouncer, mer disk för samma tabell, och VACUUM att hålla ett öga på. Följ PostgreSQL-guiden, på en VC-P Alloy.
MySQL passar appar som är skrivna för den, som WordPress, och team som kan den väl. Den var snabbast på läsning, och dess binärlogg med GTID är redo för återställning till en viss tidpunkt från början. Dess svagheter är DDL som inte går att rulla tillbaka, långsammare skrivning med binärloggen på, långsam återställning av dumpar, en stor avbild, fysiska säkerhetskopior som kräver ett separat verktyg, och funktioner som vektoravstånd som Oracle sparar till sitt moln. Följ MySQL-guiden, på en VC-P Alloy.
MariaDB passar samma appar som MySQL, med en mindre avbild, inbyggd vektorsökning, RETURNING och sekvenser, och mariadb-backup på köpet. Den var lika snabb som PostgreSQL på skrivning i vårt test. Dess svagheter är samma regler för DDL och text som MySQL, JSON som sparas som text, och mest minne i vila. Följ MariaDB-guiden, på en VC-P Alloy. Skillnaderna mellan MySQL och MariaDB går vi igenom i MySQL eller MariaDB?.
Var och en går gott och väl på en VC-P Alloy med inställningarna från sin guide. Vår VC-P Titanium körde alla tre samtidigt, vilket du bara behöver om du kör appar som kräver olika databaser på samma server.