Files
ZQYY.FQ-ETL/database/schema_verify_perf_indexes.sql

174 lines
6.2 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
$$;