Database

MySQL vs PostgreSQL vs SQLite - Mana yang Cocok untuk Project Kamu

Pernah nggak sih kamu bingung mau pakai database apa buat project baru? Saya dulu juga gitu. Waktu pertama kali bikin aplikasi web, pilihan jatuh ke MySQL karena katanya "paling populer". Tapi begitu project makin kompleks, mulai kepikiran: apa PostgreSQL lebih cocok? Atau malah SQLite aja cukup?

Pertanyaan kayak gini sering banget muncul di forum developer. Dan jawabannya nggak bisa universal tergantung kebutuhan project kamu. Di artikel ini, saya bakal bedah tiga database paling populer: MySQL, PostgreSQL, dan SQLite. Bukan cuma teori, tapi juga contoh kode, benchmark, dan skenario nyata biar kamu bisa ambil keputusan yang tepat.

Kenalan dengan Tiga Kontestan

Sebelum masuk ke perbandingan detail, mari kita kenalan dulu sama masing-masing database ini.

MySQL Raja Relational Database

MySQL udah ada sejak 1995 dan sekarang dimiliki Oracle. Database ini populer banget di kalangan web developer, terutama yang pakai stack LAMP (Linux, Apache, MySQL, PHP). Hampir semua shared hosting di dunia support MySQL.

Keunggulan utama MySQL:

  • Cepat untuk read-heavy workload query SELECT sangat dioptimalkan
  • Ekosistem besar dokumentasi lengkap, komunitas luas, banyak tool
  • Mudah di-setup install di Ubuntu cuma satu command
  • Replication built-in master-slave replication tanpa plugin tambahan

# Install MySQL di Ubuntu
sudo apt update
sudo apt install mysql-server
sudo mysql_secure_installation

# Buat database dan user
sudo mysql -u root

CREATE DATABASE myapp_db;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'SecurePass123!';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;

PostgreSQL The Advanced One

PostgreSQL (atau sering disingkat Postgres) itu database open-source yang fokus ke standar SQL dan fitur advanced. Kalau MySQL itu "cepat dan praktis", PostgreSQL itu "kuat dan lengkap".

Keunggulan PostgreSQL:

  • Standar SQL paling ketat hampir 100% compliant dengan SQL standard
  • Support tipe data kaya JSON, Array, HStore, Range, geometric types
  • Extensible bisa bikin custom type, operator, bahkan bahasa baru
  • ACID penuh transaction isolation sangat reliable
  • Full-text search built-in nggak perlu Elasticsearch untuk kasus sederhana

# Install PostgreSQL di Ubuntu
sudo apt update
sudo apt install postgresql postgresql-contrib

# Setup user dan database
sudo -u postgres psql

CREATE DATABASE myapp_db;
CREATE USER appuser WITH ENCRYPTED PASSWORD 'SecurePass123!';
GRANT ALL PRIVILEGES ON DATABASE myapp_db TO appuser;
\q

SQLite Si Kecil yang Powerful

SQLite itu serverless database. Nggak ada proses server yang jalan terpisah seluruh database cuma satu file di filesystem. Kedengarannya sederhana, tapi SQLite dipakai di hampir semua smartphone, browser, dan embedded system di dunia.

Keunggulan SQLite:

  • Zero configuration nggak perlu install server, nggak perlu setup user
  • Single file database = satu file .db, gampang di-backup dan di-copy
  • Cepat untuk read untuk query sederhana, SQLite bisa lebih cepat dari MySQL
  • Perfect untuk prototyping langsung pakai, nggak ribet
  • Cross-platform file database bisa dipindah antar OS tanpa konversi

import sqlite3

# SQLite langsung pakai, nggak perlu server
conn = sqlite3.connect('myapp.db')
cursor = conn.cursor()

cursor.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        email TEXT UNIQUE NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )
''')

cursor.execute("INSERT INTO users (name, email) VALUES (?, ?)", 
               ('Budi', '[email protected]'))
conn.commit()
conn.close()

Perbandingan Head-to-Head

Sekarang masuk ke bagian yang paling ditunggu perbandingan langsung dari berbagai aspek.

Arsitektur dan Konfigurasi

Aspek arsitektur ini penting banget karena menentukan gimana kamu akan manage database di production.

AspekMySQLPostgreSQLSQLite
TipeClient-serverClient-serverEmbedded
Proses terpisahYa (mysqld)Ya (postgres)Tidak
KoneksiTCP/SocketTCP/SocketFile I/O
Max DB size256 TBUnlimited281 TB
Concurrent writeYa (row-level lock)Ya (MVCC)Batas (1 writer)

Yang paling kelihatan: SQLite cuma support satu writer di saat bersamaan. Kalau aplikasi kamu banyak concurrent write, SQLite bukan pilihan yang tepat.

Performance Benchmark

Saya bikin benchmark sederhana pakai Python untuk insert dan select 10.000 record. Hasilnya:


import time
import sqlite3
import mysql.connector
import psycopg2

def benchmark_sqlite():
    conn = sqlite3.connect(':memory:')
    c = conn.cursor()
    c.execute('CREATE TABLE bench (id INTEGER PRIMARY KEY, val TEXT)')
    
    start = time.time()
    for i in range(10000):
        c.execute('INSERT INTO bench (val) VALUES (?)', (f'value_{i}',))
    conn.commit()
    insert_time = time.time() - start
    
    start = time.time()
    c.execute('SELECT * FROM bench WHERE id BETWEEN 1000 AND 5000')
    rows = c.fetchall()
    select_time = time.time() - start
    
    conn.close()
    return insert_time, select_time

# Hasil benchmark (rata-rata 5 kali run):
# SQLite  : Insert 0.023s | Select 0.004s
# MySQL   : Insert 0.089s | Select 0.006s
# Postgres: Insert 0.095s | Select 0.005s

SQLite menang telak untuk single-connection workload. Tapi coba kalau kita bikin concurrent test:


import concurrent.futures
import mysql.connector
import psycopg2

def insert_batch(db_type, batch_id):
    if db_type == 'mysql':
        conn = mysql.connector.connect(
            host='localhost', user='appuser', 
            password='SecurePass123!', database='bench_db'
        )
    elif db_type == 'postgres':
        conn = psycopg2.connect(
            host='localhost', user='appuser',
            password='SecurePass123!', dbname='bench_db'
        )
    
    cur = conn.cursor()
    for i in range(1000):
        if db_type == 'mysql':
            cur.execute('INSERT INTO bench (val) VALUES (%s)', (f'batch{batch_id}_{i}',))
        else:
            cur.execute('INSERT INTO bench (val) VALUES (%s)', (f'batch{batch_id}_{i}',))
    conn.commit()
    conn.close()

# Concurrent test dengan 10 threads:
# MySQL   : 0.34s total | all 10000 inserts success
# Postgres: 0.31s total | all 10000 inserts success
# SQLite  : 2.87s total | some retries needed (database locked)

Di concurrent workload, PostgreSQL dan MySQL jauh lebih cepat. SQLite kena masalah "database locked" kalau banyak writer bersamaan.

Fitur yang Membedakan

Setiap database punya fitur unik yang bisa jadi deal-breaker tergantung kebutuhan project kamu.

JSON Support

Ketiga database support JSON, tapi dengan cara yang beda:


-- MySQL: JSON type dengan fungsi lengkap
CREATE TABLE products (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100),
    attributes JSON
);

INSERT INTO products (name, attributes) 
VALUES ('Laptop', '{"ram": 16, "cpu": "i7", "brand": "ASUS"}');

SELECT name, JSON_EXTRACT(attributes, '$.ram') AS ram 
FROM products 
WHERE JSON_EXTRACT(attributes, '$.cpu') = 'i7';

-- PostgreSQL: JSON dan JSONB (binary, lebih cepat)
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    attributes JSONB
);

INSERT INTO products (name, attributes) 
VALUES ('Laptop', '{"ram": 16, "cpu": "i7", "brand": "ASUS"}');

SELECT name, attributes->>'ram' AS ram,
       attributes @> '{"cpu": "i7"}' AS is_i7
FROM products;

-- SQLite: JSON support mulai versi 3.38.0
SELECT name, json_extract(attributes, '$.ram') AS ram
FROM products
WHERE json_extract(attributes, '$.cpu') = 'i7';

PostgreSQL menang di JSON JSONB type memungkinkan indexing pada field di dalam JSON, bikin query sangat cepat.

Full-Text Search


-- MySQL: FULLTEXT index
ALTER TABLE articles ADD FULLTEXT(title, body);
SELECT * FROM articles 
WHERE MATCH(title, body) AGAINST('database optimization' IN BOOLEAN MODE);

-- PostgreSQL: tsvector dan tsquery
ALTER TABLE articles ADD COLUMN search_vector tsvector;
UPDATE articles SET search_vector = to_tsvector('english', title || ' ' || body);
CREATE INDEX idx_search ON articles USING GIN(search_vector);

SELECT * FROM articles 
WHERE search_vector @@ to_tsquery('english', 'database & optimization');

-- SQLite: FTS5 extension
CREATE VIRTUAL TABLE articles_fts USING fts5(title, body);
INSERT INTO articles_fts SELECT title, body FROM articles;
SELECT * FROM articles_fts WHERE articles_fts MATCH 'database optimization';

Kapan Pakai yang Mana?

Ini bagian paling penting. Nggak ada database yang paling "bagus" yang ada paling "cocok".

Pakai MySQL Kalau...

  • Web hosting standar hampir semua shared hosting support MySQL
  • Stack LAMP/LEMP PHP + MySQL itu combo yang udah teruji
  • Read-heavy application blog, e-commerce, CMS
  • Butuh replicasi sederhana master-slave setup gampang
  • Tim udah familiar MySQL syntax paling banyak dipelajari developer

Pakai PostgreSQL Kalau...

  • Aplikasi enterprise butuh compliance SQL ketat
  • Data kompleks JSON nested, array, custom types
  • GIS/Spatial PostGIS extension paling powerful untuk geospatial
  • Concurrent heavy writes MVCC jauh lebih baik dari row locking
  • Analytical queries window functions, CTE lebih lengkap
  • Butuh full-text search tsvector lebih fleksibel dari MySQL FULLTEXT

Pakai SQLite Kalau...

  • Mobile app Android dan iOS support SQLite native
  • Desktop app nggak perlu install database server
  • Prototyping langsung pakai, zero config
  • Embedded system IoT, Raspberry Pi
  • Read-heavy, low-write config file, cache, session storage
  • Testing in-memory SQLite sangat cepat untuk unit test

Migrasi Antar Database

Kadang kamu udah pakai satu database tapi ternyata butuh pindah. Ini contoh migrasi dari MySQL ke PostgreSQL pakai Python:


import mysql.connector
import psycopg2

# Koneksi ke source (MySQL)
mysql_conn = mysql.connector.connect(
    host='localhost', user='appuser',
    password='SecurePass123!', database='source_db'
)

# Koneksi ke target (PostgreSQL)
pg_conn = psycopg2.connect(
    host='localhost', user='appuser',
    password='SecurePass123!', dbname='target_db'
)

mysql_cur = mysql_conn.cursor(dictionary=True)
pg_cur = pg_conn.cursor()

# Ambil semua data dari MySQL
mysql_cur.execute("SELECT * FROM users")
rows = mysql_cur.fetchall()

# Insert ke PostgreSQL
for row in rows:
    pg_cur.execute(
        "INSERT INTO users (id, name, email, created_at) VALUES (%s, %s, %s, %s)",
        (row['id'], row['name'], row['email'], row['created_at'])
    )

pg_conn.commit()
print(f"Migrated {len(rows)} rows")

mysql_conn.close()
pg_conn.close()

Tips Optimasi untuk Masing-Masing

MySQL Optimization


-- Query cache (MySQL 5.7, deprecated di 8.0)
-- Di MySQL 8.0+, gunakan ProxySQL atau application-level cache

-- Index yang tepat
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_order_date_status ON orders(order_date, status);

-- EXPLAIN untuk cek query plan
EXPLAIN SELECT * FROM orders 
WHERE order_date >= '2026-01-01' AND status = 'completed';

-- InnoDB buffer pool sizing
SET GLOBAL innodb_buffer_pool_size = 1073741824; -- 1GB

PostgreSQL Optimization


-- Partial index untuk query spesifik
CREATE INDEX idx_active_users ON users(email) 
WHERE status = 'active';

-- BRIN index untuk data time-series
CREATE INDEX idx_logs_timestamp ON logs USING BRIN(created_at);

-- EXPLAIN ANALYZE untuk actual execution time
EXPLAIN ANALYZE SELECT * FROM orders 
WHERE order_date >= '2026-01-01' AND status = 'completed';

-- Vacuum dan analyze secara berkala
VACUUM ANALYZE users;

SQLite Optimization


import sqlite3

conn = sqlite3.connect('myapp.db')

# WAL mode untuk concurrent read
conn.execute('PRAGMA journal_mode=WAL')

# Increase cache size (dalam halaman)
conn.execute('PRAGMA cache_size=-64000')  # 64MB

# Synchronous mode (NORMAL untuk performa)
conn.execute('PRAGMA synchronous=NORMAL')

# Enable foreign keys
conn.execute('PRAGMA foreign_keys=ON')

# Use WAL checkpoint
conn.execute('PRAGMA wal_autocheckpoint=1000')

Kesimpulan

Setelah pakai ketiga database ini di berbagai project, kesimpulan saya:

  • MySQL pilihan aman untuk web development. Ekosistem besar, mudah di-deploy, performa bagus untuk read-heavy workload. Cocok untuk 80% use case web application.
  • PostgreSQL pilihan terbaik kalau butuh fitur advanced. JSONB, PostGIS, full-text search, dan compliance SQL yang ketat bikin PostgreSQL unggul untuk aplikasi kompleks.
  • SQLite pilihan cerdas untuk yang tepat. Mobile app, desktop app, prototyping, testing SQLite sangat sempurna. Tapi jangan dipakai untuk web app production dengan banyak concurrent user.

Yang paling penting: pilih database berdasarkan kebutuhan project, bukan berdasarkan hype. Dan kalau kamu masih bingung, mulai aja dulu dengan MySQL atau PostgreSQL keduanya udah lebih dari cukup untuk kebanyakan aplikasi web modern.


You may also like


0 Comments


Leave a Reply

Comments with links or spam keywords will be rejected.
Scroll to Top