-- Analytics Database Schema -- TimescaleDB hypertables for time-series analytics data SET search_path TO analytics, public; -- ============================================================================= -- CONTENT VIEWS: Track page/content views with time-series optimization -- ============================================================================= CREATE TABLE IF NOT EXISTS content_views ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_id UUID, session_id UUID NOT NULL, content_id VARCHAR(255) NOT NULL, content_type VARCHAR(50) NOT NULL, duration_ms INTEGER, referrer VARCHAR(500), user_agent VARCHAR(500), ip_hash VARCHAR(64), metadata JSONB DEFAULT '{}', PRIMARY KEY (id, timestamp) ); -- Convert to hypertable (7-day chunks) SELECT create_hypertable('content_views', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE ); -- ============================================================================= -- ENGAGEMENT METRICS: User interactions (likes, shares, comments, etc.) -- ============================================================================= CREATE TABLE IF NOT EXISTS engagement_metrics ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_id UUID, session_id UUID NOT NULL, metric_type VARCHAR(50) NOT NULL, target_id VARCHAR(255) NOT NULL, target_type VARCHAR(50) NOT NULL, value INTEGER DEFAULT 1, metadata JSONB DEFAULT '{}', PRIMARY KEY (id, timestamp) ); SELECT create_hypertable('engagement_metrics', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE ); -- ============================================================================= -- REVENUE METRICS: Financial tracking for analytics -- ============================================================================= CREATE TABLE IF NOT EXISTS revenue_metrics ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_id UUID NOT NULL, transaction_type VARCHAR(50) NOT NULL, amount_cents BIGINT NOT NULL, currency VARCHAR(3) DEFAULT 'USD', source VARCHAR(100), metadata JSONB DEFAULT '{}', PRIMARY KEY (id, timestamp) ); SELECT create_hypertable('revenue_metrics', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE ); -- ============================================================================= -- DASHBOARD SNAPSHOTS: Pre-computed dashboard metrics -- ============================================================================= CREATE TABLE IF NOT EXISTS dashboard_snapshots ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), user_id UUID NOT NULL, snapshot_type VARCHAR(50) NOT NULL, metrics JSONB NOT NULL, period_start TIMESTAMPTZ NOT NULL, period_end TIMESTAMPTZ NOT NULL, PRIMARY KEY (id, timestamp) ); SELECT create_hypertable('dashboard_snapshots', 'timestamp', chunk_time_interval => INTERVAL '30 days', if_not_exists => TRUE ); -- ============================================================================= -- RANKING SNAPSHOTS: Historical ranking data -- ============================================================================= CREATE TABLE IF NOT EXISTS ranking_snapshots ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), entity_id UUID NOT NULL, entity_type VARCHAR(50) NOT NULL, rank INTEGER NOT NULL, score DECIMAL(10, 4), category VARCHAR(100), metadata JSONB DEFAULT '{}', PRIMARY KEY (id, timestamp) ); SELECT create_hypertable('ranking_snapshots', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE ); -- ============================================================================= -- LISTING PERFORMANCE: Performance metrics for listings -- ============================================================================= CREATE TABLE IF NOT EXISTS listing_performance ( id BIGSERIAL, timestamp TIMESTAMPTZ NOT NULL DEFAULT NOW(), listing_id UUID NOT NULL, user_id UUID NOT NULL, views INTEGER DEFAULT 0, clicks INTEGER DEFAULT 0, conversions INTEGER DEFAULT 0, revenue_cents BIGINT DEFAULT 0, metadata JSONB DEFAULT '{}', PRIMARY KEY (id, timestamp) ); SELECT create_hypertable('listing_performance', 'timestamp', chunk_time_interval => INTERVAL '7 days', if_not_exists => TRUE ); -- ============================================================================= -- INDEXES -- ============================================================================= CREATE INDEX IF NOT EXISTS idx_content_views_user ON content_views (user_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_content_views_content ON content_views (content_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_engagement_user ON engagement_metrics (user_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_engagement_target ON engagement_metrics (target_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_revenue_user ON revenue_metrics (user_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_dashboard_user ON dashboard_snapshots (user_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_ranking_entity ON ranking_snapshots (entity_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_listing_perf_user ON listing_performance (user_id, timestamp DESC); CREATE INDEX IF NOT EXISTS idx_listing_perf_listing ON listing_performance (listing_id, timestamp DESC);