Optimasi Query PostgreSQL & MongoDB untuk Dashboard Akuntansi

Ringkasan
Strategi indexing komposit dan covering index untuk mempercepat filter rentang tanggal dan status transaksi keuangan.
Solusi konkret mengatasi N+1 Query Problem menggunakan JOIN di PostgreSQL dan denormalisasi selektif di MongoDB.
Teknik agregasi tingkat lanjut menggunakan Materialized Views dan Aggregation Pipeline untuk laporan laba rugi yang instan.
Checklist optimasi performa database untuk memastikan dashboard akuntansi tetap responsif meski data mencapai jutaan baris.
Saya masih ingat betul wajah klien yang panik saat dashboard akuntansi mereka butuh 8–12 detik hanya untuk menampilkan laporan laba rugi bulanan. Data belum sampai 500 ribu transaksi, tapi sudah terasa lambat. Setelah dicek, masalahnya klasik: indexing yang salah, N+1 query di mana-mana, dan agregasi yang dilakukan di application layer, bukan di database.
Sejak saat itu, setiap kali saya membangun atau mengoptimasi dashboard akuntansi—baik menggunakan PostgreSQL maupun MongoDB—fokus utamanya selalu sama: membuat laporan muncul dalam hitungan milidetik, bukan detik. Artikel ini merangkum strategi mendalam yang sering saya terapkan dan terbukti efektif di lingkungan production.
Mengapa Dashboard Akuntansi Mudah Mengalami Slow Query?
Data keuangan memiliki karakteristik khusus yang membuatnya rentan terhadap penurunan performa jika tidak dikelola dengan benar. Berbeda dengan data blog atau e-commerce sederhana, data akuntansi memiliki pola akses sebagai berikut:
Filter Rentang Tanggal yang Intensif: Hampir semua laporan (Neraca, Laba Rugi, Arus Kas) bergantung pada filter
transaction_date.Agregasi Berat: Penggunaan fungsi
SUM,COUNT,AVG, danGROUP BYterjadi secara masif untuk menghitung saldo akun.Relasi Data yang Dalam: Alur data biasanya mengalir dari Transaksi → Jurnal → Akun → Kategori/Header Akun.
Analisis Komparatif: User sering membandingkan periode saat ini dengan periode sebelumnya (Month-over-Month atau Year-to-Date), yang berarti database harus menjalankan dua atau lebih query agregasi besar secara simultan.
Jika query tidak dirancang dengan baik, database akan terpaksa melakukan sequential scan (membaca seluruh isi tabel) atau mengirim data mentah dalam jumlah besar ke aplikasi, yang kemudian membebani RAM server aplikasi dan memperlambat waktu respon (latency).
1. Strategi Indexing yang Tepat dan Efisien
Indexing adalah fondasi performa. Namun, perlu diingat bahwa indexing yang berlebihan justru bisa memperlambat operasi penulisan (WRITE), sementara sistem akuntansi seringkali memiliki volume transaksi yang tinggi.
Optimasi pada PostgreSQL
Untuk tabel transaksi keuangan, saya merekomendasikan penggunaan composite index. Urutan kolom dalam index sangat menentukan efektivitasnya.
-- Index untuk filter tanggal + status (paling sering dipakai untuk dashboard utama)
CREATE INDEX CONCURRENTLY idx_transactions_date_status
ON transactions (transaction_date, status);
-- Index untuk laporan per akun dengan pengurutan terbaru
CREATE INDEX CONCURRENTLY idx_transactions_account_date
ON transactions (account_id, transaction_date DESC);
-- Composite index untuk laporan laba rugi yang melibatkan tipe akun dan perusahaan
CREATE INDEX CONCURRENTLY idx_journal_entries_report
ON journal_entries (entry_date, account_type, company_id);
Tips Pro PostgreSQL:
CONCURRENTLY: Selalu gunakan keyword ini saat membuat index di production agar tabel tidak terkunci (lock) dan aplikasi tetap bisa berjalan.
Covering Index (INCLUDE): Pada PostgreSQL 11+, gunakan klausa
INCLUDEuntuk menambahkan kolom yang sering dipanggil namun tidak digunakan untuk filter. Ini memungkinkan Index Only Scan, sehingga database tidak perlu membaca heap table.EXPLAIN ANALYZE: Jangan menebak. Gunakan
EXPLAIN (ANALYZE, BUFFERS)untuk melihat apakah index benar-benar digunakan atau justru diabaikan oleh query planner.
Optimasi pada MongoDB
Di MongoDB, compound index sangat krusial karena query biasanya lebih fleksibel dan tidak kaku seperti SQL.
// Index untuk filter tanggal per perusahaan
db.transactions.createIndex({ companyId: 1, transactionDate: -1 })
// Index untuk agregasi saldo per akun
db.transactions.createIndex({ companyId: 1, accountId: 1, transactionDate: -1 })
// Index untuk status transaksi dan tanggal
db.transactions.createIndex({ status: 1, transactionDate: -1 })
Aturan emas di MongoDB adalah mengikuti pola ESR (Equality, Sort, Range). Letakkan field yang menggunakan operator equality (seperti companyId) di depan, diikuti oleh field untuk sorting, dan terakhir field untuk range (seperti transactionDate).
2. Menghindari N+1 Query Problem
N+1 Query adalah musuh terbesar dashboard yang dibangun menggunakan ORM seperti Prisma, TypeORM, atau Mongoose. Masalah ini terjadi ketika aplikasi mengambil daftar utama (1 query), lalu melakukan query tambahan untuk setiap item dalam daftar tersebut (N query).
Contoh Buruk (N+1)
// Mengambil semua transaksi (1 query)
const transactions = await Transaction.find({ companyId });
// Melakukan loop untuk mengambil nama akun (N query) - SANGAT LAMBAT
for (const tx of transactions) {
tx.account = await Account.findById(tx.accountId);
}
Solusi Efektif
PostgreSQL (JOIN Approach): Gunakan JOIN untuk menarik semua data yang dibutuhkan dalam satu kali request ke database.
SELECT
t.*,
a.name AS account_name,
a.code AS account_code
FROM transactions t
JOIN accounts a ON a.id = t.account_id
WHERE t.company_id = $1
AND t.transaction_date BETWEEN $2 AND $3;
MongoDB (Aggregation $lookup): Gunakan pipeline agregasi untuk menggabungkan koleksi.
db.transactions.aggregate([
{ $match: { companyId: ObjectId("..."), transactionDate: { $gte: start, $lte: end } } },
{
$lookup: {
from: "accounts",
localField: "accountId",
foreignField: "_id",
as: "account"
}
},
{ $unwind: "$account" }
])
Strategi Denormalisasi Selektif: Untuk data yang jarang berubah namun sering diakses (seperti accountName atau accountCode), saya menyarankan untuk menyimpan salinan data tersebut langsung di dalam dokumen transaksi. Meskipun melanggar prinsip normalisasi, trade-off ini memberikan peningkatan performa yang signifikan karena menghilangkan kebutuhan akan JOIN atau $lookup.
3. Teknik Agregasi Data Keuangan untuk Performa Milidetik
Jangan pernah menarik ribuan baris data ke Node.js atau Python hanya untuk menjumlahkannya menggunakan .reduce() atau loop. Biarkan database yang melakukan perhitungan karena mereka dioptimalkan untuk hal tersebut.
PostgreSQL: Materialized Views & Window Functions
Untuk laporan yang tidak harus real-time detik itu juga (misalnya laporan bulanan), Materialized View adalah penyelamat. Ia menyimpan hasil query secara fisik di disk.
CREATE MATERIALIZED VIEW mv_monthly_profit_loss AS
SELECT
company_id,
date_trunc('month', entry_date) AS month,
account_type,
SUM(debit) AS total_debit,
SUM(credit) AS total_credit,
SUM(credit - debit) AS net_amount
FROM journal_entries
GROUP BY 1, 2, 3;
CREATE UNIQUE INDEX ON mv_monthly_profit_loss (company_id, month, account_type);
Anda bisa melakukan REFRESH MATERIALIZED VIEW CONCURRENTLY setiap 15 menit atau setelah proses closing periode akuntansi selesai.
MongoDB: Aggregation Pipeline yang Efisien
Kunci dari MongoDB Aggregation adalah memfilter data sebanyak mungkin di tahap awal.
db.transactions.aggregate([
{
$match: {
companyId: ObjectId("..."),
transactionDate: { $gte: ISODate("2025-01-01"), $lte: ISODate("2025-12-31") },
status: "posted"
}
},
{
$group: {
_id: {
month: { $dateToString: { format: "%Y-%m", date: "$transactionDate" } },
accountId: "$accountId"
},
totalDebit: { $sum: "$debit" },
totalCredit: { $sum: "$credit" },
count: { $sum: 1 }
}
},
{
$lookup: {
from: "accounts",
localField: "_id.accountId",
foreignField: "_id",
as: "account"
}
},
{ $sort: { "_id.month": 1 } }
])
Perbandingan Strategi Optimasi
Masalah | PostgreSQL Solution | MongoDB Solution | Dampak Performa |
|---|---|---|---|
Filter Tanggal & Status | Composite Index | Compound Index (ESR) | Sangat Tinggi |
N+1 Query | JOIN / Prisma include | $lookup / Denormalisasi | Tinggi |
Agregasi Bulanan | Materialized View | Aggregation Pipeline | Sangat Tinggi |
Laporan Real-time | Partial Index + Caching | Covered Query + Caching | Tinggi |
Write-heavy Period | Index Minimalis | Background Indexing | Sedang |
Checklist Optimasi Akhir
Sebelum melakukan deploy ke production, pastikan Anda telah melewati checklist berikut:
Semua query laporan utama telah diuji dengan
EXPLAIN ANALYZE.Index dibuat berdasarkan pola filter yang paling sering muncul (bukan asal buat index di semua kolom).
Tidak ada loop query (N+1) di endpoint dashboard utama.
Perhitungan total/sum dilakukan di level database.
Implementasi caching (seperti Redis) untuk data yang jarang berubah (misal: daftar akun).
Monitoring slow query aktif menggunakan
pg_stat_statements(Postgres) atau MongoDB Profiler.
Penutup
Dashboard akuntansi yang cepat bukan hanya soal kenyamanan teknis, tetapi juga soal membangun kepercayaan pengguna. Ketika seorang CFO atau akuntan bisa melihat laporan laba rugi muncul dalam 200–400 ms, mereka akan merasa sistem tersebut handal dan profesional.
Kombinasi antara indexing yang presisi, penghindaran N+1, dan pemanfaatan fitur agregasi bawaan database sudah cukup untuk membuat sebagian besar dashboard akuntansi terasa sangat responsif, bahkan dengan volume data jutaan baris. Jika Anda masih mengalami bottleneck, jangan ragu untuk meninjau kembali skema database dan pola query Anda.
Perlu aplikasi akunting yang dapat disesuaikan dengan kebutuhan perusahaanmu? mari kita diskusikan kebutuhanya disini https://www.pradha.id/products/smart-accounting
Solusi yang relevan
Jasa Pembuatan Website
Pembuatan website custom yang cepat, modern, dan siap jualan.
Related Articles

Small AI Models 2026: Cost-Efficiency & Edge Computing
Explore how small AI models like GPT-5.6 Luna and Gemma 4 are slashing costs and enabling powerful offline capabilities on consumer hardware in 2026.

Keyboard-Driven GUIs: Efficiency Beyond the Mouse
Can we replace the mouse entirely? Explore the technical and philosophical debate over keyboard-driven GUIs, featuring tools like Neovim and 'neverclick' that prioritize high-efficiency workflows.

Samsung LPDDR5X-PIM: Revolutionizing On-Device AI Memory
Samsung's LPDDR5X-PIM integrates MAC units into DRAM banks to deliver 8x more bandwidth, enabling smartphones to run 8B parameter LLMs locally with 3x faster inference.

GTA VI Release Date, Gameplay Details & PS5 Availability
Rockstar Games has officially set the release date for Grand Theft Auto VI for November 19, 2026. Discover the latest on the dual protagonists Jason and Lucia, PS5 exclusivity, and the reactive world of Vice City.
Dapatkan Artikel Terbaru!
Berlangganan newsletter kami untuk mendapatkan tips dan insight menarik langsung ke inbox Anda.
Kami tidak akan pernah membagikan email Anda (No Spam).