Caching mechanism
Database Caching Mechanisms
Caching improves database performance by storing frequently accessed data in memory, reducing the need for expensive disk I/O operations.
1. Types of Caching
1.1 Application-Level Caching
- Data is cached in the application layer before querying the database again.
- Common tools: Redis, Memcached, in-memory caching (e.g., Python’s
functools.lru_cache).
✅ Example: Flask + Redis Caching
import redis
import psycopg2
cache = redis.Redis(host='localhost', port=6379, db=0)
conn = psycopg2.connect("dbname=mydb user=postgres")
def get_user(user_id):
cached = cache.get(f"user:{user_id}")
if cached:
return cached.decode("utf-8") # Return from cache
cur = conn.cursor()
cur.execute("SELECT name FROM users WHERE id = %s", (user_id,))
user = cur.fetchone()
cache.setex(f"user:{user_id}", 3600, user[0]) # Cache for 1 hour
return user[0]
1.2 Database-Level Caching
- The database itself caches frequently used queries and indexes.
- Examples: PostgreSQL’s
shared_buffers, MySQL’s Query Cache (deprecated in MySQL 8).
✅ PostgreSQL Query Cache Tuning
SHOW shared_buffers;
ALTER SYSTEM SET shared_buffers = '256MB';
✅ MySQL Query Cache (Pre-MySQL 8)
SET GLOBAL query_cache_size = 1000000;
SET GLOBAL query_cache_type = ON;
1.3 Reverse Proxy Caching (Edge Caching)
- A caching layer sits between the application and database, reducing repeated queries.
- Examples: Varnish, Cloudflare, Nginx FastCGI Cache.
✅ Nginx FastCGI Cache Example
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;
server {
location /api/ {
proxy_cache my_cache;
proxy_pass http://backend_server;
}
}
1.4 Object-Level Caching
- Store objects instead of raw database queries.
- Example: Django ORM caching
✅ Example: Django + Memcached
from django.core.cache import cache
user = cache.get(f"user_{user_id}")
if not user:
user = User.objects.get(id=user_id)
cache.set(f"user_{user_id}", user, timeout=3600)
2. Cache Expiration & Eviction Strategies
2.1 Time-to-Live (TTL)
- Cached data expires after a set time.
- Example:
cache.set(key, value, ex=3600)(expires in 1 hour).
2.2 Least Recently Used (LRU)
- Removes the least recently used items when cache is full.
- Redis and Memcached support LRU eviction.
✅ Enable LRU in Redis
redis-cli config set maxmemory-policy allkeys-lru
2.3 Write-Through vs. Write-Back Caching
- Write-Through: Data is written to the cache and database simultaneously.
- Write-Back: Data is written to the cache first, then periodically flushed to the database.
✅ Example: Write-Through Cache in Python
def set_user(user_id, name):
conn.cursor().execute("UPDATE users SET name=%s WHERE id=%s", (name, user_id))
cache.set(f"user:{user_id}", name) # Update cache immediately
3. Best Practices
✅ Use Redis or Memcached for high-speed caching.
✅ Implement TTL & eviction strategies to prevent stale data.
✅ Use database query caching where supported (PostgreSQL’s pg_stat_statements).
✅ Consider CDN caching for large-scale applications.
✅ Always test cache performance with benchmarking tools (e.g., redis-benchmark).
Caching significantly reduces database load and improves response times, but improper cache management can lead to stale data or unnecessary memory usage.