SET client_encoding TO "UTF8"; -- ============================================================================ -- 校验性能索引(ODS / DWD) -- ---------------------------------------------------------------------------- -- 用途: -- 1) 加速校验查询(主键查找、窗口扫描、当前版本扫描)。 -- 2) 保持数据语义不变(仅添加索引 + ANALYZE,不改写业务数据)。 -- -- 注意事项: -- 1) 本脚本具有幂等性(`CREATE INDEX IF NOT EXISTS`)。 -- 2) 如有严格的在线 DDL 要求,请手动使用 `CREATE INDEX CONCURRENTLY` -- 在维护安全模式下执行(不可在事务块内运行)。 -- ============================================================================ DO $$ DECLARE rec RECORD; pk_cols TEXT[]; pk_cols_sql TEXT; idx_name TEXT; BEGIN FOR rec IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'billiards_ods' AND table_type = 'BASE TABLE' LOOP IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'billiards_ods' AND table_name = rec.table_name AND column_name = 'fetched_at' ) THEN idx_name := left(format('idx_%s_vfy_fetched_at', rec.table_name), 50) || '_' || substr(md5(rec.table_name || '_vfy_fetched_at'), 1, 8); EXECUTE format( 'CREATE INDEX IF NOT EXISTS %I ON billiards_ods.%I (fetched_at)', idx_name, rec.table_name ); SELECT array_agg(kcu.column_name ORDER BY kcu.ordinal_position) INTO pk_cols FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.table_schema = kcu.table_schema AND tc.table_name = kcu.table_name AND tc.constraint_name = kcu.constraint_name WHERE tc.table_schema = 'billiards_ods' AND tc.table_name = rec.table_name AND tc.constraint_type = 'PRIMARY KEY'; IF pk_cols IS NOT NULL AND coalesce(array_length(pk_cols, 1), 0) <= 3 THEN SELECT string_agg(format('%I', c), ', ') INTO pk_cols_sql FROM unnest(pk_cols) AS c; idx_name := left(format('idx_%s_vfy_fetched_pk', rec.table_name), 50) || '_' || substr(md5(rec.table_name || '_vfy_fetched_pk'), 1, 8); EXECUTE format( 'CREATE INDEX IF NOT EXISTS %I ON billiards_ods.%I (fetched_at, %s)', idx_name, rec.table_name, pk_cols_sql ); END IF; END IF; END LOOP; END $$; DO $$ DECLARE rec RECORD; tcol TEXT; pk_cols TEXT[]; pk_cols_sql TEXT; idx_name TEXT; time_candidates TEXT[] := ARRAY[ 'pay_time', 'create_time', 'start_use_time', 'scd2_start_time', 'calc_time', 'order_date', 'fetched_at' ]; BEGIN FOR rec IN SELECT table_name FROM information_schema.tables WHERE table_schema = 'billiards_dwd' AND table_type = 'BASE TABLE' LOOP SELECT array_agg(kcu.column_name ORDER BY kcu.ordinal_position) INTO pk_cols FROM information_schema.table_constraints tc JOIN information_schema.key_column_usage kcu ON tc.table_schema = kcu.table_schema AND tc.table_name = kcu.table_name AND tc.constraint_name = kcu.constraint_name WHERE tc.table_schema = 'billiards_dwd' AND tc.table_name = rec.table_name AND tc.constraint_type = 'PRIMARY KEY'; IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'billiards_dwd' AND table_name = rec.table_name AND column_name = 'scd2_is_current' ) AND pk_cols IS NOT NULL AND coalesce(array_length(pk_cols, 1), 0) BETWEEN 1 AND 4 THEN SELECT string_agg(format('%I', c), ', ') INTO pk_cols_sql FROM unnest(pk_cols) AS c; idx_name := left(format('idx_%s_vfy_pk_current', rec.table_name), 50) || '_' || substr(md5(rec.table_name || '_vfy_pk_current'), 1, 8); EXECUTE format( 'CREATE INDEX IF NOT EXISTS %I ON billiards_dwd.%I (%s, scd2_is_current)', idx_name, rec.table_name, pk_cols_sql ); END IF; FOREACH tcol IN ARRAY time_candidates LOOP IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_schema = 'billiards_dwd' AND table_name = rec.table_name AND column_name = tcol ) THEN idx_name := left(format('idx_%s_vfy_%s', rec.table_name, tcol), 50) || '_' || substr(md5(rec.table_name || '_vfy_' || tcol), 1, 8); EXECUTE format( 'CREATE INDEX IF NOT EXISTS %I ON billiards_dwd.%I (%I)', idx_name, rec.table_name, tcol ); IF pk_cols IS NOT NULL AND coalesce(array_length(pk_cols, 1), 0) <= 3 THEN SELECT string_agg(format('%I', c), ', ') INTO pk_cols_sql FROM unnest(pk_cols) AS c; idx_name := left(format('idx_%s_vfy_%s_pk', rec.table_name, tcol), 50) || '_' || substr(md5(rec.table_name || '_vfy_' || tcol || '_pk'), 1, 8); EXECUTE format( 'CREATE INDEX IF NOT EXISTS %I ON billiards_dwd.%I (%I, %s)', idx_name, rec.table_name, tcol, pk_cols_sql ); END IF; END IF; END LOOP; END LOOP; END $$; DO $$ DECLARE rec RECORD; BEGIN FOR rec IN SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema IN ('billiards_ods', 'billiards_dwd') AND table_type = 'BASE TABLE' LOOP EXECUTE format('ANALYZE %I.%I', rec.table_schema, rec.table_name); END LOOP; END $$;