NVMe SSD Performance Tuning for Databases: Maximize IOPS and Throughput

Why NVMe SSD Tuning Matters
NVMe SSDs deliver dramatically higher IOPS and lower latency than traditional SSDs or HDDs. However, default Linux settings are often not optimized for NVMe drives. Without proper tuning, you may be leaving 30-50% of potential performance on the table.
ServerRaja cloud servers offer NVMe SSD storage that can deliver hundreds of thousands of IOPS. This guide shows you how to extract maximum performance from your NVMe drives for database workloads.
Verifying Your NVMe Drive
First, confirm you have an NVMe drive and check its capabilities:
# List NVMe devices
sudo nvme list# Get detailed device information sudo nvme id-ctrl /dev/nvme0n1
# Check current firmware version sudo nvme fw-log /dev/nvme0n1
# View SMART health data sudo nvme smart-log /dev/nvme0n1
# Check current I/O statistics cat /proc/diskstats | grep nvme iostat -x 1 5 | grep nvme ```
I/O Scheduler Configuration
The I/O scheduler determines how read and write requests are queued. For NVMe drives, the `none` (noop) scheduler is optimal since NVMe has its own internal scheduling:
# Check current scheduler
cat /sys/block/nvme0n1/queue/scheduler# Set to none (noop) for NVMe echo none | sudo tee /sys/block/nvme0n1/queue/scheduler
# Make permanent via udev rule cat <<EOF | sudo tee /etc/udev/rules.d/60-nvme-scheduler.rules ACTION=="add|change", KERNEL=="nvme[0-9]*n[0-9]", ATTR{queue/scheduler}="none" EOF
# Reload udev rules sudo udevadm control --reload-rules sudo udevadm trigger ```
Filesystem Optimization
Using XFS for Database Workloads
XFS is generally the best filesystem for database workloads on NVMe:
# Create XFS filesystem with optimized options
sudo mkfs.xfs -f -d agcount=32 -l size=128m /dev/nvme0n1p1# Mount with performance options sudo mount -o noatime,nodiratime,logbufs=8,logbsize=256k,allocsize=64m /dev/nvme0n1p1 /data
# Add to /etc/fstab for persistence echo '/dev/nvme0n1p1 /data xfs noatime,nodiratime,logbufs=8,logbsize=256k,allocsize=64m 0 0' | sudo tee -a /etc/fstab ```
Using ext4 as an Alternative
# Create ext4 filesystem
sudo mkfs.ext4 -O ^has_journal -E stride=128,stripe-width=256 /dev/nvme0n1p1# Or with journal (for data safety) sudo mkfs.ext4 -E stride=128,stripe-width=256 /dev/nvme0n1p1
# Mount with optimizations sudo mount -o noatime,nodiratime,data=writeback,barrier=0,commit=60 /dev/nvme0n1p1 /data ```
Kernel I/O Parameters
Optimize kernel parameters for NVMe performance:
# /etc/sysctl.d/99-nvme-performance.conf# Increase the maximum number of I/O requests vm.nr_requests = 4096
# Reduce dirty page writeback frequency vm.dirty_ratio = 40 vm.dirty_background_ratio = 10
# Set dirty page writeback interval (centiseconds) vm.dirty_writeback_centisecs = 3000 vm.dirty_expire_centisecs = 6000
# Increase max sectors per I/O request # (check current: cat /sys/block/nvme0n1/queue/max_sectors_kb) ```
sudo sysctl -p /etc/sysctl.d/99-nvme-performance.conf# Increase queue depth for NVMe echo 1024 | sudo tee /sys/block/nvme0n1/queue/nr_requests
# Increase read-ahead buffer echo 256 | sudo tee /sys/block/nvme0n1/queue/read_ahead_kb ```
Database-Specific Tuning
PostgreSQL on NVMe
Optimize PostgreSQL configuration for NVMe storage:
# postgresql.conf# Shared buffers - 25% of total RAM shared_buffers = 4GB
# Effective cache size - 75% of total RAM effective_cache_size = 12GB
# Increase WAL buffers for write performance wal_buffers = 64MB
# Use direct I/O for better performance effective_io_concurrency = 200 maintenance_io_concurrency = 200
# Async commit for better write throughput (trade durability for speed) # synchronous_commit = off # Only for non-critical data
# Random page cost - lower for SSDs (default is 4.0 for HDD) random_page_cost = 1.1 seq_page_cost = 1.0
# Increase work memory for complex queries work_mem = 256MB
# Parallel query settings max_parallel_workers_per_gather = 4 max_parallel_workers = 8 max_worker_processes = 16
# Checkpoint tuning checkpoint_completion_target = 0.9 max_wal_size = 4GB min_wal_size = 1GB ```
MySQL/MariaDB on NVMe
Optimize InnoDB for NVMe storage:
# /etc/mysql/mysql.conf.d/nvme-optimizations.cnf[mysqld] # InnoDB buffer pool - 70-80% of available RAM innodb_buffer_pool_size = 12G innodb_buffer_pool_instances = 12
# Use O_DIRECT for I/O (bypasses OS cache) innodb_flush_method = O_DIRECT
# Increase I/O capacity for NVMe innodb_io_capacity = 10000 innodb_io_capacity_max = 20000
# Flush neighbors setting - 0 for NVMe (no need to flush adjacent pages) innodb_flush_neighbors = 0
# Increase log file size for better write performance innodb_log_file_size = 2G innodb_log_buffer_size = 256M
# Doublewrite buffer can be disabled on NVMe with battery-backed cache # innodb_doublewrite = off
# Increase read/write I/O threads innodb_read_io_threads = 16 innodb_write_io_threads = 16
# Adaptive hash index innodb_adaptive_hash_index = ON
# Change buffer innodb_change_buffer_max_size = 25
# Page size - consider 16K (default) or 64K for NVMe innodb_page_size = 16K ```
Benchmarking Database Performance
PostgreSQL Benchmarking with pgbench
# Initialize pgbench
pgbench -i -s 100 mydb# Run standard benchmark pgbench -c 32 -j 8 -T 300 mydb
# Read-only benchmark pgbench -c 32 -j 8 -T 300 -S mydb ```
MySQL Benchmarking with sysbench
# Prepare benchmark tables
sysbench oltp_read_write \
--mysql-host=localhost \
--mysql-user=root \
--mysql-password=password \
--mysql-db=sbtest \
--tables=10 \
--table-size=1000000 \
prepare# Run read-write benchmark sysbench oltp_read_write \ --mysql-host=localhost \ --threads=32 \ --time=300 \ --report-interval=10 \ run
# Run read-only benchmark sysbench oltp_read_only \ --mysql-host=localhost \ --threads=32 \ --time=300 \ run ```
Monitoring NVMe Health
Set up SMART monitoring for your NVMe drives:
# Install smartmontools
sudo apt install smartmontools# Enable NVMe monitoring sudo smartctl -a /dev/nvme0n1
# Set up automatic monitoring cat <<EOF | sudo tee /etc/smartd.conf /dev/nvme0n1 -a -o on -S on -s (S/../.././02|L/../../6/03) -m [email protected] EOF
sudo systemctl enable --now smartd ```
Conclusion
NVMe SSDs are a game-changer for database performance, but only when properly configured. Set the I/O scheduler to `none`, use an optimized filesystem mount, tune your database configuration for SSD characteristics, and benchmark regularly. ServerRaja NVMe cloud servers provide the raw performance; these optimizations help your databases fully utilize it.