--- sidebar_position: 2 --- # Tables Reference Internal tables and schema used by `pg_ttl_index`. ## ttl_index_table The main configuration and statistics table for TTL indexes. ### Schema ```sql CREATE TABLE ttl_index_table ( schema_name TEXT NOT NULL DEFAULT 'public', table_name TEXT NOT NULL, column_name TEXT NOT NULL, expire_after_seconds INTEGER NOT NULL, active BOOLEAN NOT NULL DEFAULT true, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), last_run TIMESTAMPTZ, batch_size INTEGER NOT NULL DEFAULT 10000, rows_deleted_last_run BIGINT DEFAULT 0, total_rows_deleted BIGINT DEFAULT 0, index_name TEXT, soft_delete_column TEXT, index_created_by_extension BOOLEAN NOT NULL DEFAULT false, PRIMARY KEY (schema_name, table_name, column_name) ); ``` ### Columns | Column | Type | Nullable | Default | Description | |--------|------|----------|---------|-------------| | `schema_name` | TEXT | No | `public` | Schema containing the TTL-enabled table | | `table_name` | TEXT | No | - | Name of the table with TTL enabled | | `column_name` | TEXT | No | - | Timestamp column name for expiration | | `expire_after_seconds` | INTEGER | No | - | Seconds before data expires | | `active` | BOOLEAN | No | `true` | Whether TTL is currently active | | `created_at` | TIMESTAMPTZ | No | `NOW()` | When TTL was first created | | `updated_at` | TIMESTAMPTZ | Yes | `NOW()` | Last configuration update | | `last_run` | TIMESTAMPTZ | Yes | `NULL` | Last cleanup execution time | | `batch_size` | INTEGER | No | `10000` | Rows to delete per batch | | `rows_deleted_last_run` | BIGINT | Yes | `0` | Rows deleted in last cleanup | | `total_rows_deleted` | BIGINT | Yes | `0` | Total rows deleted all-time | | `index_name` | TEXT | Yes | `NULL` | Name of auto-created index | | `soft_delete_column` | TEXT | Yes | `NULL` | Timestamp column used for soft delete mode | | `index_created_by_extension` | BOOLEAN | No | `false` | Whether the tracked index was created by `pg_ttl_index` | ### Primary Key `(schema_name, table_name, column_name)` - Ensures one TTL configuration per table/column pair per schema. ## Querying ttl_index_table ### View All TTL Configurations ```sql SELECT * FROM ttl_index_table ORDER BY schema_name, table_name, column_name; ``` ### Active TTL Indexes Only ```sql SELECT schema_name, table_name, column_name, expire_after_seconds FROM ttl_index_table WHERE active = true; ``` ### Recent Activity ```sql SELECT schema_name, table_name, last_run, NOW() - last_run AS time_since_last, rows_deleted_last_run FROM ttl_index_table WHERE last_run IS NOT NULL ORDER BY last_run DESC; ``` ### Tables with High Deletion Rate ```sql SELECT schema_name, table_name, total_rows_deleted, rows_deleted_last_run FROM ttl_index_table ORDER BY total_rows_deleted DESC LIMIT 10; ``` ## Direct Manipulation (Advanced) :::warning Advanced Usage Direct manipulation is for advanced users. Use the [API functions](functions.md) for normal operations. ::: ### Temporarily Disable TTL ```sql -- Disable cleanup without removing configuration UPDATE ttl_index_table SET active = false WHERE schema_name = 'public' AND table_name = 'user_sessions'; ``` ### Change Expiry Time ```sql -- Update expiration period UPDATE ttl_index_table SET expire_after_seconds = 7200, -- 2 hours updated_at = NOW() WHERE schema_name = 'public' AND table_name = 'user_sessions' AND column_name = 'created_at'; ``` ### Adjust Batch Size ```sql -- Increase batch size for better performance UPDATE ttl_index_table SET batch_size = 50000 WHERE schema_name = 'public' AND table_name = 'app_logs'; ``` ### Reset Statistics ```sql -- Reset deletion counters UPDATE ttl_index_table SET rows_deleted_last_run = 0, total_rows_deleted = 0 WHERE schema_name = 'public' AND table_name = 'user_sessions'; ``` ### Re-enable TTL ```sql -- Re-activate disabled TTL UPDATE ttl_index_table SET active = true, updated_at = NOW() WHERE schema_name = 'public' AND table_name = 'user_sessions'; ``` ## Monitoring Queries ### Tables Never Cleaned ```sql SELECT schema_name, table_name, column_name, created_at, NOW() - created_at AS age FROM ttl_index_table WHERE last_run IS NULL AND active = true; ``` ### Stale Cleanup Detection ```sql -- Find tables where cleanup hasn't run recently SELECT schema_name, table_name, last_run, NOW() - last_run AS time_since_cleanup FROM ttl_index_table WHERE active = true AND last_run < NOW() - INTERVAL '5 minutes' ORDER BY last_run; ``` ### Deletion Efficiency ```sql -- Average rows deleted per run SELECT schema_name, table_name, total_rows_deleted, CASE WHEN last_run > created_at THEN total_rows_deleted::FLOAT / EXTRACT(EPOCH FROM (last_run - created_at)) * 60 ELSE 0 END AS avg_rows_per_minute FROM ttl_index_table WHERE active = true; ``` ## Schema Notes ### Indexing Strategy The `ttl_index_table` itself is small (typically < 100 rows) and doesn't require additional indexes. The primary key on `(schema_name, table_name, column_name)` provides efficient lookups. ### Statistics Tracking Statistics (`rows_deleted_last_run`, `total_rows_deleted`) are updated after each cleanup run. These counters: - Are **cumulative** for `total_rows_deleted` - Reset on each run for `rows_deleted_last_run` - Never overflow (using BIGINT type) ### Active Flag The `active` flag allows you to: - Temporarily disable TTL without losing configuration - Re-enable later without reconfiguring - Keep historical data (created_at, total_rows_deleted) ## Best Practices ### Don't Bypass the API Use [`ttl_create_index()`](functions.md#ttl_create_index) and [`ttl_drop_index()`](functions.md#ttl_drop_index) instead of direct INSERT/DELETE: ❌ **Bad:** ```sql INSERT INTO ttl_index_table (schema_name, table_name, column_name, expire_after_seconds) VALUES ('public', 'my_table', 'created_at', 3600); ``` ✅ **Good:** ```sql SELECT ttl_create_index('public.my_table', 'created_at', 3600); ``` ### Use ttl_summary() for Monitoring Instead of querying `ttl_index_table` directly, use [`ttl_summary()`](functions.md#ttl_summary) which includes computed fields: ✅ **Better:** ```sql SELECT * FROM ttl_summary(); ``` ### Backup TTL Configuration Include `ttl_index_table` in your backup strategy: ```sql -- Export TTL configuration COPY ttl_index_table TO '/backup/ttl_config.csv' CSV HEADER; -- Restore TTL configuration COPY ttl_index_table FROM '/backup/ttl_config.csv' CSV HEADER; ``` ## See Also - [Functions API](functions.md) - Recommended way to manage TTL - [Monitoring Guide](../guides/monitoring.md) - How to track TTL activity - [Best Practices](../guides/best-practices.md) - Optimization tips