---
title: "CONCURRENT REFRESH MATERIALIZED VIEW - Quick Reference"
---

# CONCURRENT REFRESH MATERIALIZED VIEW - Quick Reference

## TL;DR

CONCURRENT refresh provides zero-downtime updates to materialized views using atomic table swap.

## Usage

### Non-Concurrent (Fast, Brief Downtime)
```sql
REFRESH MATERIALIZED VIEW order_summary;
```

### Concurrent (Zero Downtime, Higher Overhead)
```sql
REFRESH MATERIALIZED VIEW order_summary CONCURRENTLY;
```

## When to Use

### Use CONCURRENT When:
- Production system requiring 24/7 availability
- Materialized view is actively queried
- Refresh takes more than a few seconds
- Downtime is unacceptable

### Use Non-Concurrent When:
- Maintenance window available
- View is not actively queried
- Refresh is very fast (< 1 second)
- Storage space is constrained

## How It Works

```
1. Create temp table: __mv_view__temp_<timestamp>
2. Populate temp table (old data still readable)
3. Atomic swap:
   - Rename: __mv_view → __mv_view__old_<timestamp>
   - Rename: __mv_view__temp_<timestamp> → __mv_view
4. Drop backup table
```

**Zero Downtime:** Queries always have a valid table to read from.

## Performance Impact

| Aspect | Non-Concurrent | Concurrent |
|--------|---------------|-----------|
| Query Downtime | ~ms to seconds | 0 |
| Storage Overhead | 0 | 2x (temporary) |
| Refresh Time | Baseline | +10-20% (rename overhead) |
| Suitable for Prod | No | Yes |

## Error Handling

All errors are handled gracefully:
- **Before swap:** Temp table cleaned up, original untouched
- **During swap:** Automatic rollback to original state
- **After swap:** Refresh successful, orphaned backups logged

## Monitoring

### Key Metrics
- **Refresh duration:** Time from start to completion
- **Storage overhead:** Peak storage usage during refresh
- **Swap time:** Duration of atomic rename operations
- **Cleanup success:** Percentage of successful backup deletions

### Log Messages

**Success:**
```
INFO: Successfully stored 10000 rows for materialized view 'order_summary' (CONCURRENT mode)
```

**Failure:**
```
ERROR: Failed to rename temp table to main table
INFO: Successfully restored original table
```

## Common Issues

### Issue: Orphaned Backup Tables

**Symptom:** Tables named `__mv_*__old_*` in catalog

**Cause:** Cleanup failed after successful refresh

**Fix:**
```sql
-- List orphaned tables
SELECT table_name FROM heliosdb_tables
WHERE table_name LIKE '__mv_%__old_%';

-- Manual cleanup (safe to drop)
DROP TABLE __mv_order_summary__old_1234567890;
```

### Issue: Insufficient Storage

**Symptom:** Refresh fails with "No space left" error

**Cause:** Concurrent refresh needs 2x storage temporarily

**Fix:**
- Use non-concurrent refresh during maintenance
- Free up storage space
- Increase available storage

### Issue: Long Refresh Time

**Symptom:** Concurrent refresh takes much longer than non-concurrent

**Cause:** Large dataset with many rename operations

**Solution:**
- Expected behavior for large views
- Consider incremental refresh (future feature)
- Use non-concurrent during maintenance window

## Best Practices

### 1. Monitor Storage
```sql
-- Check MV size before concurrent refresh
SELECT
    view_name,
    row_count,
    pg_size_pretty(pg_total_relation_size('__mv_' || view_name))
FROM heliosdb_materialized_views;
```

### 2. Schedule Refreshes
```sql
-- Use concurrent for business hours
REFRESH MATERIALIZED VIEW order_summary CONCURRENTLY;

-- Use non-concurrent for off-hours (faster)
REFRESH MATERIALIZED VIEW order_summary;
```

### 3. Test First
```sql
-- Test with small MV first
REFRESH MATERIALIZED VIEW test_view CONCURRENTLY;

-- Then production MVs
REFRESH MATERIALIZED VIEW production_view CONCURRENTLY;
```

### 4. Monitor Logs
```bash
# Watch refresh operations
tail -f heliosdb.log | grep "CONCURRENT"

# Check for errors
grep -i "CRITICAL\|ERROR" heliosdb.log | grep "materialized"
```

## Testing

Run the tests:
```bash
cargo test concurrent_mv_refresh_tests
```

Individual tests:
```bash
cargo test test_concurrent_mv_refresh_basic
cargo test test_catalog_rename_table
```

## Implementation Files

**Core Implementation:**

**Tests:**

**Documentation:**

## FAQ

**Q: Does CONCURRENT guarantee no query failures?**
A: Yes, the atomic rename ensures a valid table exists at all times.

**Q: What happens if the system crashes during refresh?**
A: Original table remains intact. Orphaned temp/backup tables can be cleaned manually.

**Q: Can I cancel a CONCURRENT refresh?**
A: Not currently. Wait for completion or restart the database (original table remains safe).

**Q: Is CONCURRENT slower than non-concurrent?**
A: Slightly (~10-20% overhead from rename operations), but the difference is usually negligible compared to query execution time.

**Q: How much extra storage is needed?**
A: Approximately 2x the size of the materialized view (temporary table during refresh).

**Q: Can I use CONCURRENT with large views (100M+ rows)?**
A: Yes, but ensure sufficient storage. The algorithm is O(n) and handles large datasets.

## Quick Decision Tree

```
Do you need zero downtime?
├─ YES → Use CONCURRENT
└─ NO → Do you have storage constraints?
    ├─ YES → Use non-concurrent
    └─ NO → Is refresh time critical?
        ├─ YES → Use non-concurrent (faster)
        └─ NO → Use CONCURRENT (safer)
```

## Summary

**Use CONCURRENT when:** Production availability matters more than performance
**Use non-concurrent when:** Performance matters more than availability

**Default recommendation:** CONCURRENT for production, non-concurrent for development/testing.
