-- ============================================================================
-- PostgreSQL 18 --- SQL 数据采样与近似聚合 (Data Sampling and Approximation)
-- 场景: 万亿数据高并发 / 国际时区时间差 / 国际多种货币结算
-- 本文件【自包含·完全幂等】: 重复运行结果逐字节一致 (setseed 保证造数一致)
-- 连接方式: PGPASSWORD=<your_password> psql -U postgres -h localhost -p 5433 -d jewelry_pg -f 本文件
--
-- 本专题聚焦: 当全表精确计算代价过高 (万亿行) 时, 用采样与统计近似快速得到可接受的估计。
-- - TABLESAMPLE BERNOULLI(p) / SYSTEM(p) : 行级 / 块级 随机抽样
-- - TABLESAMPLE ... REPEATABLE(seed) : 可重复的确定性采样 (幂等关键)
-- - 采样估计 (estimate = sample_metric / p) : 总行数 / 总销售额 / 均值 的近似
-- - pg_stats.n_distinct / pg_class.reltuples : 免全表扫描的 distinct / 行数估计
-- - 采样分位数 / 置信区间 / 手动 Bernoulli : 近似聚合与误差量化
-- - 物化视图预聚合 : 近似看板的最快路径
-- ============================================================================
\timing off
SET client_min_messages = warning; -- 抑制 DROP/CREATE/VACUUM 的 NOTICE, 保证重跑幂等
SET max_parallel_workers_per_gather = 0; -- 关并行, 使块统计稳定(万亿级可据需开启)
SET random_page_cost = 1.1;
SET seq_page_cost = 1.0;
SET effective_cache_size = '4GB';
SET TIME ZONE 'UTC'; -- 使 extract()/AT TIME ZONE 计算基于 UTC, 与时区演示形成可比基准
-- ----------------------------------------------------------------------------
-- 0. 度量框架 (DROP + CREATE, 幂等)
-- pg_plan_stats : 抓真实执行计划 (Actual Rows / 共享块 / 扫描节点类型)
-- pg_find_scan : 下钻到真正的扫描节点 (顶层常是 Aggregate/WindowAgg/Recursive)
-- pg_plan_text_has : 检查计划文本是否含某关键字 (FOR 循环拼接多行)
-- pg_demo_v : 自检登记
-- pg_demo_err_probe : 捕获真实报错
-- ----------------------------------------------------------------------------
DROP FUNCTION IF EXISTS pg_plan_stats(text) CASCADE;
CREATE OR REPLACE FUNCTION pg_plan_stats(
p_sql text,
OUT actual_rows bigint,
OUT shared_blks bigint,
OUT node_type text)
RETURNS record LANGUAGE plpgsql AS $$
DECLARE j json;
BEGIN
EXECUTE 'EXPLAIN (ANALYZE, TIMING OFF, FORMAT JSON) ' || p_sql INTO j;
actual_rows := (j->0->'Plan'->>'Actual Rows')::numeric::bigint;
shared_blks := COALESCE((j->0->'Plan'->>'Shared Hit Blocks')::numeric::bigint,0)
+ COALESCE((j->0->'Plan'->>'Shared Read Blocks')::numeric::bigint,0);
node_type := pg_find_scan(j->0->'Plan');
END $$;
DROP FUNCTION IF EXISTS pg_find_scan(json) CASCADE;
CREATE OR REPLACE FUNCTION pg_find_scan(cur json) RETURNS text LANGUAGE plpgsql AS $$
DECLARE nt text;
BEGIN
nt := cur->>'Node Type';
IF nt LIKE '%Scan' THEN RETURN nt; END IF;
IF cur->'Plans' IS NOT NULL AND json_array_length(cur->'Plans') > 0 THEN
RETURN pg_find_scan(cur->'Plans'->0);
END IF;
RETURN nt;
END $$;
DROP FUNCTION IF EXISTS pg_plan_text_has(text, text) CASCADE;
CREATE OR REPLACE FUNCTION pg_plan_text_has(p_sql text, p_sub text) RETURNS boolean LANGUAGE plpgsql AS $$
DECLARE r record; t text := '';
BEGIN
FOR r IN EXECUTE 'EXPLAIN (FORMAT TEXT) ' || p_sql LOOP
t := t || r."QUERY PLAN";
END LOOP;
RETURN position(p_sub in t) > 0;
END $$;
DROP TABLE IF EXISTS pg_demo_check;
CREATE TABLE pg_demo_check (
name text PRIMARY KEY,
pass int,
detail text
);
DROP FUNCTION IF EXISTS pg_demo_v(text,int,text) CASCADE;
CREATE OR REPLACE FUNCTION pg_demo_v(p_name text, p_pass int, p_detail text)
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO pg_demo_check(name,pass,detail) VALUES (p_name,p_pass,p_detail)
ON CONFLICT (name) DO UPDATE SET pass=EXCLUDED.pass, detail=EXCLUDED.detail;
END $$;
DROP TABLE IF EXISTS pg_demo_probe;
CREATE TABLE pg_demo_probe (
label text PRIMARY KEY,
sqlstate text,
msg text
);
DROP FUNCTION IF EXISTS pg_demo_err_probe(text,text) CASCADE;
CREATE OR REPLACE FUNCTION pg_demo_err_probe(p_label text, p_sql text)
RETURNS void LANGUAGE plpgsql AS $$
DECLARE e text; s text;
BEGIN
BEGIN
EXECUTE p_sql;
INSERT INTO pg_demo_probe(label,sqlstate,msg) VALUES (p_label,'OK','执行成功')
ON CONFLICT (label) DO UPDATE SET sqlstate='OK', msg='执行成功';
EXCEPTION WHEN OTHERS THEN
GET STACKED DIAGNOSTICS s=RETURNED_SQLSTATE, e=MESSAGE_TEXT;
INSERT INTO pg_demo_probe(label,sqlstate,msg) VALUES (p_label,s,e)
ON CONFLICT (label) DO UPDATE SET sqlstate=EXCLUDED.sqlstate, msg=EXCLUDED.msg;
END;
END $$;
-- ----------------------------------------------------------------------------
-- 1. 事实表 pg_txn (八域中台 10 万行交易事实; 与同系列脚本同种子, 保证语境一致)
-- system_code 直接承载 8 个业务域 OA/ERP/CRM/HRM/MES/SCM/WMS/KMS
-- created_utc 为 UTC; tz / create_local_date 为各 Office 本地时区折算 (演示时区差)
-- amount_orig 原币, amount_usd 统一美元折算口径 (跨币种不可直接相加)
-- ----------------------------------------------------------------------------
DROP TABLE IF EXISTS pg_txn CASCADE;
CREATE TABLE pg_txn (
txn_id bigint PRIMARY KEY,
system_code text NOT NULL,
customer_id int,
product_id int,
supplier_id int,
warehouse_id int,
emp_id int,
country_code text,
currency_code text,
amount_orig numeric(14,2),
amount_usd numeric(14,4),
created_utc timestamptz,
tz text GENERATED ALWAYS AS (
CASE country_code
WHEN 'CN' THEN 'Asia/Shanghai' WHEN 'HK' THEN 'Asia/Hong_Kong'
WHEN 'US' THEN 'America/New_York' WHEN 'JP' THEN 'Asia/Tokyo'
WHEN 'DE' THEN 'Europe/Berlin' WHEN 'FR' THEN 'Europe/Paris'
WHEN 'GB' THEN 'Europe/London' WHEN 'SG' THEN 'Asia/Singapore'
WHEN 'AU' THEN 'Australia/Sydney' WHEN 'IN' THEN 'Asia/Kolkata'
ELSE 'UTC' END) STORED,
create_local_date date GENERATED ALWAYS AS (
(created_utc AT TIME ZONE (
CASE country_code
WHEN 'CN' THEN 'Asia/Shanghai' WHEN 'HK' THEN 'Asia/Hong_Kong'
WHEN 'US' THEN 'America/New_York' WHEN 'JP' THEN 'Asia/Tokyo'
WHEN 'DE' THEN 'Europe/Berlin' WHEN 'FR' THEN 'Europe/Paris'
WHEN 'GB' THEN 'Europe/London' WHEN 'SG' THEN 'Asia/Singapore'
WHEN 'AU' THEN 'Australia/Sydney' WHEN 'IN' THEN 'Asia/Kolkata'
ELSE 'UTC' END))::date) STORED,
reference_no text UNIQUE,
note text,
rand_val double precision
);
DO $$
BEGIN
PERFORM setseed(0.20261020);
INSERT INTO pg_txn (txn_id, system_code, customer_id, product_id, supplier_id, warehouse_id,
emp_id, country_code, currency_code, amount_orig, amount_usd,
created_utc, reference_no, note, rand_val)
SELECT n,
(ARRAY['OA','ERP','CRM','HRM','MES','SCM','WMS','KMS'])[1+(n%8)],
1+((n+n/8)%10000),
1+(n%2000),
1+(n%200),
1+(n%50),
1+(n%500),
(ARRAY['CN','HK','US','JP','DE','FR','GB','SG','AU','IN'])[1+((n/8)%10)],
(ARRAY['CNY','HKD','USD','JPY','EUR','EUR','GBP','SGD','AUD','INR'])[1+((n/8)%10)],
round((100 + random()*90000)::numeric,2),
round(((100 + random()*90000) /
(CASE (ARRAY['CNY','HK','USD','JPY','EUR','EUR','GBP','SGD','AUD','INR'])[1+((n/8)%10)]
WHEN 'CNY' THEN 7.10 WHEN 'HKD' THEN 7.80 WHEN 'USD' THEN 1.00
WHEN 'JPY' THEN 150.0 WHEN 'EUR' THEN 0.92 WHEN 'GBP' THEN 0.79
WHEN 'SGD' THEN 1.35 WHEN 'AUD' THEN 1.52 WHEN 'INR' THEN 83.0 END))::numeric,4),
'2025-01-01 00:00:00+00'::timestamptz + ((random()*300*24*3600)::integer * interval '1 second'),
'REF-'||lpad(n::text,8,'0'),
(ARRAY['Diamond','Gold','Pearl','Ruby','Sapphire','Emerald','Platinum','Tanzanite','Jade','Onyx','Zirconia','Topaz'])[1+(n%12)] || ' order for VIP client',
random()
FROM generate_series(1,100000) n;
END $$;
CREATE INDEX idx_txn_cover ON pg_txn (system_code, amount_usd);
CREATE INDEX idx_txn_created ON pg_txn (created_utc);
CREATE INDEX idx_txn_localday ON pg_txn (create_local_date);
CREATE INDEX idx_txn_cust ON pg_txn (customer_id);
CREATE INDEX idx_txn_emp ON pg_txn (emp_id);
CREATE INDEX idx_txn_sys_ctry ON pg_txn (system_code, country_code);
CREATE INDEX brin_txn_created ON pg_txn USING brin (created_utc);
VACUUM ANALYZE pg_txn;
-- 万亿级语境内存提示: 真实环境 pg_txn 为分区表 (按 created_utc 月分区) + 每分区独立统计;
-- 以下采样/近似演示在 10 万行样本上给出可复现结论, 方法对万亿行直接等量放大即可。
-- ----------------------------------------------------------------------------
-- 2. 演示: 数据采样与近似聚合
-- ----------------------------------------------------------------------------
\echo '=== §1 基础采样: BERNOULLI(行级) vs SYSTEM(块级), 均带 REPEATABLE 确定性种子 ==='
SELECT 'BERNOULLI(5) REPEATABLE(42)' AS method, count(*) AS sampled_rows
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42);
SELECT 'SYSTEM(5) REPEATABLE(7)' AS method, count(*) AS sampled_rows
FROM pg_txn TABLESAMPLE SYSTEM(5) REPEATABLE(7);
\echo '=== §2 近似估算: 用 5% 采样估计全表 总行数 / 总销售额(USD), 并量化误差 ==='
WITH exact AS (
SELECT count(*) AS n_all, sum(amount_usd) AS s_all FROM pg_txn
),
samp AS (
SELECT count(*) AS n_s, sum(amount_usd) AS s_s
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(99)
)
SELECT
exact.n_all AS exact_rows,
round(samp.n_s / 0.05) AS est_rows,
round(100.0*abs(samp.n_s/0.05 - exact.n_all)/exact.n_all, 2) AS rows_err_pct,
round(exact.s_all,2) AS exact_usd,
round(samp.s_s / 0.05,2) AS est_usd,
round(100.0*abs(samp.s_s/0.05 - exact.s_all)/exact.s_all, 2) AS usd_err_pct
FROM exact, samp;
\echo '=== §3 近似去重: 采样估计 distinct 业务域/国家; 对比 pg_stats.n_distinct 免全表估计 ==='
SELECT count(DISTINCT system_code) AS sampled_distinct_system,
count(DISTINCT country_code) AS sampled_distinct_country
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(123);
SELECT attname, n_distinct
FROM pg_stats
WHERE tablename='pg_txn' AND attname IN ('system_code','country_code')
ORDER BY attname;
\echo '=== §4 免全表扫描行数估计: pg_class.reltuples (ANALYZE 后维护的规划器估计) ==='
SELECT relname, reltuples::bigint AS estimated_rows
FROM pg_class WHERE relname='pg_txn';
\echo '=== §5 近似分位数: 50% 采样估算中位数, 对比精确中位数 ==='
WITH exact AS (
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY amount_usd) AS m FROM pg_txn
),
samp AS (
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY amount_usd) AS m
FROM pg_txn TABLESAMPLE BERNOULLI(50) REPEATABLE(5)
)
SELECT round(exact.m::numeric,2) AS exact_median, round(samp.m::numeric,2) AS sample_median,
round(100.0*abs(samp.m::numeric-exact.m::numeric)/NULLIF(exact.m::numeric,0),2) AS err_pct
FROM exact, samp;
\echo '=== §6 近似极值覆盖性: 采样子集 min/max 必落在全表 min/max 区间内 (子集性质) ==='
WITH f0 AS (
SELECT min(amount_usd) AS fmin, max(amount_usd) AS fmax FROM pg_txn
),
samp AS (
SELECT min(amount_usd) AS smin, max(amount_usd) AS smax
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42)
)
SELECT f0.fmin, f0.fmax, samp.smin, samp.smax,
CASE WHEN samp.smin>=f0.fmin AND samp.smax<=f0.fmax THEN 'subset-ok' ELSE 'violation' END AS check_res
FROM f0, samp;
\echo '=== §7 置信区间: 基于样本均值与标准差构 95% CI 估计全表均值 ==='
WITH s AS (
SELECT avg(amount_usd) AS m, stddev_pop(amount_usd) AS sd, count(*) AS n
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(99)
)
SELECT round(m::numeric,2) AS sample_mean, round(sd::numeric,2) AS sample_sd,
round(m::numeric - 1.96*sd::numeric/sqrt(n::numeric),2) AS ci_low,
round(m::numeric + 1.96*sd::numeric/sqrt(n::numeric),2) AS ci_high
FROM s;
\echo '=== §8 手动 Bernoulli: WHERE random()<p 与 TABLESAMPLE 等价思路 (注意 random 消耗序列) ==='
SELECT count(*) AS manual_bernoulli_rows
FROM pg_txn WHERE random() < 0.05;
\echo '=== §9 国际时区: 采样行按本地时区折算, 展示时区差导致 UTC 日期与本地日期跨界 ==='
SELECT country_code, tz,
count(*) AS n,
count(*) FILTER (WHERE create_local_date <> (created_utc AT TIME ZONE 'UTC')::date) AS cross_day_rows
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(3)
GROUP BY country_code, tz
ORDER BY country_code
LIMIT 10;
\echo '=== §10 国际多币种: 采样子集估计 USD 总额; 原币金额不可跨币种直接相加 ==='
SELECT count(DISTINCT currency_code) AS sampled_distinct_ccy,
round(sum(amount_usd) / 0.05, 2) AS est_total_usd,
round(sum(amount_orig) / 0.05, 2) AS est_total_orig_mixed_wrong
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(123);
\echo '=== §11 执行计划: TABLESAMPLE 产生 Sample Scan 节点 (万亿级避免全表扫描的关键信号) ==='
EXPLAIN (FORMAT TEXT)
SELECT count(*) FROM pg_txn TABLESAMPLE BERNOULLI(10);
\echo '=== §12 物化视图预聚合: 近似看板的最快路径 (域级聚合后行数极小) ==='
DROP MATERIALIZED VIEW IF EXISTS mv_domain_gmv;
CREATE MATERIALIZED VIEW mv_domain_gmv AS
SELECT system_code, count(*) AS txn_cnt, sum(amount_usd) AS gmv_usd
FROM pg_txn GROUP BY system_code;
SELECT system_code, txn_cnt, round(gmv_usd,2) AS gmv_usd
FROM mv_domain_gmv ORDER BY system_code;
-- ----------------------------------------------------------------------------
-- 3. 自检 V1--V18 (全部基于 REPEATABLE 采样, 保证连跑幂等; 误差类检查留足容差)
-- ----------------------------------------------------------------------------
DO $$
DECLARE v_a bigint; v_b bigint; v_c bigint; v_d bigint;
exact_sum numeric; samp_sum numeric; est numeric;
exact_med numeric; samp_med numeric;
est1 numeric; est2 numeric;
full_blks bigint; mv_blks bigint; mv_rows int;
nd_system numeric; relt bigint;
cross_day int; dist_ccy int;
BEGIN
-- V1 全表精确行数 (校验造数)
PERFORM pg_demo_v('V1_full_count',
(SELECT CASE WHEN count(*)=100000 THEN 1 ELSE 0 END FROM pg_txn),
'exact rows='||(SELECT count(*) FROM pg_txn));
-- V2 BERNOULLI(5) REPEATABLE(42) 确定性: 两次相同 + 规模合理
SELECT count(*) INTO v_a FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42);
SELECT count(*) INTO v_b FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42);
PERFORM pg_demo_v('V2_bernoulli_deterministic',
(SELECT CASE WHEN v_a=v_b AND v_a BETWEEN 3500 AND 6500 THEN 1 ELSE 0 END),
'a='||v_a||' b='||v_b);
-- V3 SYSTEM(5) REPEATABLE(7) 确定性
SELECT count(*) INTO v_c FROM pg_txn TABLESAMPLE SYSTEM(5) REPEATABLE(7);
SELECT count(*) INTO v_d FROM pg_txn TABLESAMPLE SYSTEM(5) REPEATABLE(7);
PERFORM pg_demo_v('V3_system_deterministic',
(SELECT CASE WHEN v_c=v_d AND v_c BETWEEN 3500 AND 6500 THEN 1 ELSE 0 END),
'c='||v_c||' d='||v_d);
-- V4 5% 采样估计总销售额(USD) 误差 < 20%
SELECT sum(amount_usd) INTO exact_sum FROM pg_txn;
SELECT sum(amount_usd) INTO samp_sum FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(99);
est := samp_sum / 0.05;
PERFORM pg_demo_v('V4_sum_estimate',
(SELECT CASE WHEN abs(est-exact_sum)/exact_sum < 0.20 THEN 1 ELSE 0 END),
'est='||round(est,2)||' exact='||round(exact_sum,2)||' err%='||round(100*abs(est-exact_sum)/exact_sum,2));
-- V5 采样 distinct 业务域覆盖 (5% 样本必含全部 8 域)
PERFORM pg_demo_v('V5_sampled_distinct_system',
(SELECT CASE WHEN count(DISTINCT system_code)=8 THEN 1 ELSE 0 END
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(123)),
'distinct_system=8');
-- V6 pg_stats.n_distinct 估计 system_code 接近 8
SELECT n_distinct INTO nd_system FROM pg_stats
WHERE tablename='pg_txn' AND attname='system_code';
PERFORM pg_demo_v('V6_stats_ndistinct',
(SELECT CASE WHEN abs(nd_system - 8) <= 2 THEN 1 ELSE 0 END),
'n_distinct='||nd_system);
-- V7 pg_class.reltuples 行数估计 < 10% 误差
SELECT reltuples::bigint INTO relt FROM pg_class WHERE relname='pg_txn';
PERFORM pg_demo_v('V7_reltuples_estimate',
(SELECT CASE WHEN abs(relt-100000)::numeric/100000 < 0.10 THEN 1 ELSE 0 END),
'reltuples='||relt);
-- V8 50% 采样中位数 误差 < 10%
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY amount_usd) INTO exact_med FROM pg_txn;
SELECT percentile_cont(0.5) WITHIN GROUP (ORDER BY amount_usd) INTO samp_med
FROM pg_txn TABLESAMPLE BERNOULLI(50) REPEATABLE(5);
PERFORM pg_demo_v('V8_median_estimate',
(SELECT CASE WHEN abs(samp_med-exact_med)/NULLIF(exact_med,0) < 0.10 THEN 1 ELSE 0 END),
'sample='||round(samp_med,2)||' exact='||round(exact_med,2));
-- V9 极值覆盖性 (采样子集 min>=全表min, max<=全表max)
PERFORM pg_demo_v('V9_extreme_coverage',
(SELECT CASE WHEN (SELECT min(amount_usd) FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42)) >= (SELECT min(amount_usd) FROM pg_txn)
AND (SELECT max(amount_usd) FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42)) <= (SELECT max(amount_usd) FROM pg_txn)
THEN 1 ELSE 0 END),
'subset-min<=full-min & subset-max>=full-max 恒成立');
-- V10 手动 Bernoulli 规模合理 (3500-6500)
PERFORM pg_demo_v('V10_manual_bernoulli',
(SELECT CASE WHEN count(*) BETWEEN 3500 AND 6500 THEN 1 ELSE 0 END
FROM pg_txn WHERE random() < 0.05),
'manual bernoulli size sanity');
-- V11 时区跨界 (采样中存在本地日期 != UTC 日期的行)
SELECT count(*) FILTER (WHERE create_local_date <> (created_utc AT TIME ZONE 'UTC')::date)
INTO cross_day
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(3);
PERFORM pg_demo_v('V11_timezone_cross_day',
(SELECT CASE WHEN cross_day > 0 THEN 1 ELSE 0 END),
'cross_day_rows='||cross_day);
-- V12 采样覆盖全部 distinct 货币 (全表 EUR 重复故仅 9 种; 见造数数组)
SELECT count(DISTINCT currency_code) INTO dist_ccy
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(123);
PERFORM pg_demo_v('V12_sampled_ccy_coverage',
(SELECT CASE WHEN dist_ccy = 9 THEN 1 ELSE 0 END),
'distinct_ccy='||dist_ccy||' (全表 EUR 重复, distinct=9)');
-- V13 两个不同种子的采样估计均落在 20% 容差内 (方法一致性)
SELECT sum(amount_usd)/0.05 INTO est1 FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(99);
SELECT sum(amount_usd)/0.05 INTO est2 FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(456);
PERFORM pg_demo_v('V13_estimate_consistency',
(SELECT CASE WHEN abs(est1-exact_sum)/exact_sum < 0.20
AND abs(est2-exact_sum)/exact_sum < 0.20 THEN 1 ELSE 0 END),
'est1='||round(est1,2)||' est2='||round(est2,2));
-- V14 计划含 Sample Scan 节点
PERFORM pg_demo_v('V14_sample_scan_plan',
(SELECT CASE WHEN pg_plan_text_has('SELECT count(*) FROM pg_txn TABLESAMPLE BERNOULLI(10)', 'Sample Scan') THEN 1 ELSE 0 END),
'TABLESAMPLE 生成 Sample Scan');
-- V15 物化视图预聚合: 8 行 + 扫描块数 < 全表
SELECT count(*) INTO mv_rows FROM mv_domain_gmv;
SELECT shared_blks INTO full_blks FROM pg_plan_stats('SELECT sum(amount_usd) FROM pg_txn');
SELECT shared_blks INTO mv_blks FROM pg_plan_stats('SELECT sum(gmv_usd) FROM mv_domain_gmv');
PERFORM pg_demo_v('V15_mv_approx',
(SELECT CASE WHEN mv_rows=8 AND mv_blks < full_blks THEN 1 ELSE 0 END),
'mv_rows='||mv_rows||' mv_blks='||mv_blks||' full_blks='||full_blks);
-- V16 采样覆盖全部 8 业务域 (REPEATABLE 42)
PERFORM pg_demo_v('V16_sample_coverage',
(SELECT CASE WHEN count(DISTINCT system_code)=8 THEN 1 ELSE 0 END
FROM pg_txn TABLESAMPLE BERNOULLI(5) REPEATABLE(42)),
'all 8 domains in sample');
-- V17 BERNOULLI 与 SYSTEM 规模均在合理区间 (采样方法健全性)
PERFORM pg_demo_v('V17_sample_size_sanity',
(SELECT CASE WHEN v_a BETWEEN 3500 AND 6500 AND v_c BETWEEN 3500 AND 6500 THEN 1 ELSE 0 END),
'bernoulli='||v_a||' system='||v_c);
-- V18 全部通过: 排除自身后, 17 项功能检查必须全为 1
PERFORM pg_demo_v('V18_all_pass',
(SELECT CASE WHEN count(*)=17 AND count(*)=count(*)FILTER(WHERE pass=1) THEN 1 ELSE 0 END
FROM pg_demo_check WHERE name <> 'V18_all_pass'),
'17 functional checks all pass=1');
END $$;
-- ----------------------------------------------------------------------------
-- 4. 自检汇总 (SELECT 输出, 不受 client_min_messages=warning 抑制)
-- ----------------------------------------------------------------------------
SELECT name, pass, detail FROM pg_demo_check ORDER BY name;
SELECT CASE WHEN count(*)=count(*) FILTER (WHERE pass=1) THEN 'ALL PASS' ELSE 'SOME FAILED' END AS result,
count(*) AS total,
count(*) FILTER (WHERE pass=1) AS passed
FROM pg_demo_check;