PostgreSQL High Disk I/O: Emergency Optimization Techniques for PostgreSQL 8.3


2 views

When your PostgreSQL 8.3 server shows consistently high disk I/O (visible via tools like atop with DSK in red), it's often a sign that the database is performing excessive disk reads/writes instead of utilizing available RAM. In your case, the server has 16GB RAM but only 24MB allocated to shared_buffers - a critical misconfiguration.

While some optimizations require a restart, here are immediate actions:

-- Increase work_mem for better sort/hash operations (per session)
SET work_mem = '64MB';

-- Temporarily reduce checkpoint frequency
ALTER SYSTEM SET checkpoint_segments = 16;
ALTER SYSTEM SET checkpoint_timeout = '15min';

-- Enable sequential scan avoidance
SET enable_seqscan = off;

For your dedicated 16GB server running PostgreSQL 8.3:

-- These require restart but are critical for long-term health
# postgresql.conf (example values for 16GB system):
shared_buffers = 4GB                # 25% of total RAM
effective_cache_size = 12GB         # 75% of total RAM
work_mem = 16MB                     # Adjust per connection basis
maintenance_work_mem = 512MB
random_page_cost = 1.1              # For SSDs

Identify problematic queries with:

-- Find high-I/O queries
SELECT query, calls, total_time, shared_blks_hit, shared_blks_read
FROM pg_stat_statements
ORDER BY shared_blks_read DESC
LIMIT 10;

-- Add missing indexes (example)
CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders(user_id);

When you can schedule brief downtime:

-- Clean up dead tuples without full VACUUM
VACUUM (VERBOSE, ANALYZE) problematic_table;

-- For extreme cases, consider:
SET synchronous_commit = off;  -- Risk data loss on crash

Verify improvements with:

-- Check buffer hit rate (aim for >99%)
SELECT sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) as ratio
FROM pg_statio_user_tables;

-- Monitor checkpoint activity
SELECT * FROM pg_stat_bgwriter;

When atop shows constant DSK usage in red for PostgreSQL 8.3, you're dealing with a serious I/O bottleneck. With 16GB RAM mostly idle while shared_buffers sits at just 24MB, we've identified our first optimization target.

While we can't modify shared_buffers without restart, we can leverage these dynamic parameters:

# Increase work memory per operation
ALTER SYSTEM SET work_mem = '16MB';  -- Default is 1MB
SELECT pg_reload_conf();

# Boost maintenance operations
ALTER SYSTEM SET maintenance_work_mem = '256MB';  -- Helps VACUUM, CREATE INDEX
SELECT pg_reload_conf();

Create a RAM disk for temporary files if you have spare memory:

# Linux tmpfs setup (as root)
mkdir /mnt/pgtmp
mount -t tmpfs -o size=2048m tmpfs /mnt/pgtmp

# Then inform PostgreSQL
ALTER SYSTEM SET temp_tablespaces = 'pg_default,pg_temp';
ALTER SYSTEM SET temp_file_limit = '2GB';  -- Prevent runaway temp usage
SELECT pg_reload_conf();

Identify and throttle heavy queries without killing them:

-- Find top I/O offenders
SELECT pid, query_start, query 
FROM pg_stat_activity 
WHERE wait_event_type = 'IO' 
ORDER BY query_start;

-- Use pg_sleep() in application code for heavy queries
BEGIN;
SELECT pg_sleep(0.1);  -- 100ms delay
-- Your heavy query here
COMMIT;

When you can't wait for proper indexing:

-- Create partial indexes for common filters
CREATE INDEX CONCURRENTLY idx_orders_active ON orders(id) WHERE status = 'active';

-- Convert sequential scans to index scans
SET enable_seqscan = off;  -- Session-level only
-- Run problematic queries here

For immediate relief from write amplification:

-- Prioritize vacuuming bloated tables
VACUUM (VERBOSE, ANALYZE) transactions;

-- Enable aggressive autovacuum for critical tables
ALTER TABLE large_table SET (
  autovacuum_vacuum_cost_delay = 10,
  autovacuum_vacuum_cost_limit = 1000
);

Adjust write flushing behavior:

-- Spread out checkpoint writes
ALTER SYSTEM SET checkpoint_completion_target = 0.9;  -- Default 0.5
ALTER SYSTEM SET checkpoint_timeout = '30min';  -- Default 5min
SELECT pg_reload_conf();