当前位置: 首页 > news >正文

Postgresql TPC-H OLAP测试全流程

编译

1. 测试能否进入 PostgreSQL

先执行:

sudo -u postgres psql -c "SELECT version();"

如果能输出 PostgreSQL 版本,说明数据库服务正常。


2. 创建 TPC-H 测试数据库

你当前 Linux 用户是 xueqing,先检查 PostgreSQL 里有没有同名用户:

sudo -u postgres psql -c "\du"

如果里面没有 xueqing,执行:

sudo -u postgres createuser -s xueqing

然后创建数据库:

createdb tpch

测试连接:

psql -d tpch -c "SELECT current_database(), current_user;"

正常的话应该看到类似:

 current_database | current_user
------------------+--------------tpch             | xueqing

如果 createdb tpch 提示数据库已存在,可以忽略,继续下一步。


3. 进入 dbgen 目录

你现在在:

~/TPCH/TPC-H

进入官方数据生成工具目录:

cd ~/TPCH/TPC-H/dbgen
ls

你应该能看到类似这些文件:

makefile.suite
dss.ddl
dss.ri
queries

4. 编译 TPC-H 工具

复制 Makefile:

cp makefile.suite Makefile

编辑:

vim Makefile

找到这几行,改成:

CC      = gcc
DATABASE= POSTGRESQL
MACHINE = LINUX
WORKLOAD = TPCH

保存退出后执行:

make

编译成功后检查:

ls -l dbgen qgen

如果能看到 dbgenqgen,说明编译成功。


修复 qgen 编译失败

这个问题通常是因为你在 Makefile 里设置了:

DATABASE= POSTGRESQL

但你这份官方工具源码里没有完整的 PostgreSQL 宏定义,所以 qgen.c 编译时找不到这些宏。

进入目录:

cd ~/TPCH/TPC-H/dbgen

先查这些宏定义应该在哪个文件里:

grep -R "SET_ROWCOUNT\|START_TRAN\|GEN_QUERY_PLAN" -n .

大概率会看到它们在 tpcd.h 或类似头文件里,对 DB2ORACLEINFORMIX 有定义,但没有 POSTGRESQL

然后执行下面这个补丁命令:

cp tpcd.h tpcd.h.bakcat >> tpcd.h <<'EOF'/* PostgreSQL definitions added for qgen compile */
#ifdef POSTGRESQL
#define SET_ROWCOUNT "-- SET_ROWCOUNT %d"
#define START_TRAN "BEGIN;"
#define END_TRAN "COMMIT;"
#define SET_DBASE "-- SET_DBASE %s"
#define SET_OUTPUT "\\o"
#define GEN_QUERY_PLAN "EXPLAIN"
#endif
EOF

然后重新编译:

make clean
make

5. 生成 SF=1 测试数据

先跑小规模 1GB:

./dbgen -s 1

检查生成的数据文件:

ls *.tbl

然后去掉每行末尾多余的 |

for f in *.tbl; dosed -i 's/|$//' "$f"
done

6. 建表并导入数据

建表:

psql -d tpch -f dss.ddl

创建导入脚本:

cat > load.sql <<'SQL'
\set ON_ERROR_STOP on\copy region   from 'region.tbl'   with (format csv, delimiter '|');
\copy nation   from 'nation.tbl'   with (format csv, delimiter '|');
\copy supplier from 'supplier.tbl' with (format csv, delimiter '|');
\copy customer from 'customer.tbl' with (format csv, delimiter '|');
\copy part     from 'part.tbl'     with (format csv, delimiter '|');
\copy partsupp from 'partsupp.tbl' with (format csv, delimiter '|');
\copy orders   from 'orders.tbl'   with (format csv, delimiter '|');
\copy lineitem from 'lineitem.tbl' with (format csv, delimiter '|');
SQL

导入:

psql -d tpch -f load.sql

导入完成后建约束:

psql -d tpch -f dss.ri

收集统计信息:

psql -d tpch -c "VACUUM ANALYZE;"

你现在建议直接从这里开始执行:

sudo -u postgres psql -c "SELECT version();"
sudo -u postgres psql -c "\du"
sudo -u postgres createuser -s xueqing
createdb tpch
psql -d tpch -c "SELECT current_database(), current_user;"

如果 createusercreatedb 报“already exists”,不是问题,继续往下走。

7. 生成数据 建表 导入数据

编译成功后:

./dbgen -s 1

去掉 .tbl 每行最后的多余 |

for f in *.tbl; dosed -i 's/|$//' "$f"
done

建表:

psql -d tpch -f dss.ddl

然后导入数据。

数据导入

1. 先确认 .tbl 文件都在

在当前目录执行:

ls -lh *.tbl

应该能看到:

customer.tbl
lineitem.tbl
nation.tbl
orders.tbl
part.tbl
partsupp.tbl
region.tbl
supplier.tbl

2. 创建导入脚本

~/TPCH/TPC-H/dbgen 目录下执行:

cat > load.sql <<'SQL'
\set ON_ERROR_STOP on\copy region   from 'region.tbl'   with (format csv, delimiter '|');
\copy nation   from 'nation.tbl'   with (format csv, delimiter '|');
\copy supplier from 'supplier.tbl' with (format csv, delimiter '|');
\copy customer from 'customer.tbl' with (format csv, delimiter '|');
\copy part     from 'part.tbl'     with (format csv, delimiter '|');
\copy partsupp from 'partsupp.tbl' with (format csv, delimiter '|');
\copy orders   from 'orders.tbl'   with (format csv, delimiter '|');
\copy lineitem from 'lineitem.tbl' with (format csv, delimiter '|');
SQL

3. 执行导入

psql -d tpch -f load.sql

这一步会花一点时间,尤其是 lineitem.tbl 有 600 万行左右。

成功时会看到类似:

COPY 5
COPY 25
COPY 10000
COPY 150000
COPY 200000
COPY 800000
COPY 1500000
COPY 6001215

4. 检查导入行数

导入完成后执行:

psql -d tpch -c "
SELECT 'region' AS table_name, count(*) FROM region
UNION ALL SELECT 'nation', count(*) FROM nation
UNION ALL SELECT 'supplier', count(*) FROM supplier
UNION ALL SELECT 'customer', count(*) FROM customer
UNION ALL SELECT 'part', count(*) FROM part
UNION ALL SELECT 'partsupp', count(*) FROM partsupp
UNION ALL SELECT 'orders', count(*) FROM orders
UNION ALL SELECT 'lineitem', count(*) FROM lineitem;
"

SF=1 正常结果大概是:

region       5
nation       25
supplier     10000
customer     150000
part         200000
partsupp     800000
orders       1500000
lineitem     6001215

PostgreSQL 版主键外键添加

1. 新建 PostgreSQL 版约束脚本

因为是先删除,再创建,所以会有这样的信息:

psql:pg_ri.sql:9: NOTICE: constraint "partsupp_fk2" of relation "partsupp" does not exist, skipping
ALTER TABLE
psql:pg_ri.sql:10: NOTICE: constraint "customer_fk1" of relation "customer" does not exist, skipping
ALTER TABLE
psql:pg_ri.sql:11: NOTICE: constraint "supplier_fk1" of relation "supplier" does not exist, skipping

cat > pg_ri.sql <<'SQL'
\set ON_ERROR_STOP onBEGIN;ALTER TABLE lineitem DROP CONSTRAINT IF EXISTS lineitem_fk1;
ALTER TABLE lineitem DROP CONSTRAINT IF EXISTS lineitem_fk2;
ALTER TABLE orders DROP CONSTRAINT IF EXISTS orders_fk1;
ALTER TABLE partsupp DROP CONSTRAINT IF EXISTS partsupp_fk1;
ALTER TABLE partsupp DROP CONSTRAINT IF EXISTS partsupp_fk2;
ALTER TABLE customer DROP CONSTRAINT IF EXISTS customer_fk1;
ALTER TABLE supplier DROP CONSTRAINT IF EXISTS supplier_fk1;
ALTER TABLE nation DROP CONSTRAINT IF EXISTS nation_fk1;ALTER TABLE lineitem DROP CONSTRAINT IF EXISTS lineitem_pkey;
ALTER TABLE orders DROP CONSTRAINT IF EXISTS orders_pkey;
ALTER TABLE partsupp DROP CONSTRAINT IF EXISTS partsupp_pkey;
ALTER TABLE part DROP CONSTRAINT IF EXISTS part_pkey;
ALTER TABLE customer DROP CONSTRAINT IF EXISTS customer_pkey;
ALTER TABLE supplier DROP CONSTRAINT IF EXISTS supplier_pkey;
ALTER TABLE nation DROP CONSTRAINT IF EXISTS nation_pkey;
ALTER TABLE region DROP CONSTRAINT IF EXISTS region_pkey;ALTER TABLE regionADD CONSTRAINT region_pkey PRIMARY KEY (r_regionkey);ALTER TABLE nationADD CONSTRAINT nation_pkey PRIMARY KEY (n_nationkey);ALTER TABLE supplierADD CONSTRAINT supplier_pkey PRIMARY KEY (s_suppkey);ALTER TABLE customerADD CONSTRAINT customer_pkey PRIMARY KEY (c_custkey);ALTER TABLE partADD CONSTRAINT part_pkey PRIMARY KEY (p_partkey);ALTER TABLE partsuppADD CONSTRAINT partsupp_pkey PRIMARY KEY (ps_partkey, ps_suppkey);ALTER TABLE ordersADD CONSTRAINT orders_pkey PRIMARY KEY (o_orderkey);ALTER TABLE lineitemADD CONSTRAINT lineitem_pkey PRIMARY KEY (l_orderkey, l_linenumber);ALTER TABLE nationADD CONSTRAINT nation_fk1FOREIGN KEY (n_regionkey) REFERENCES region (r_regionkey);ALTER TABLE supplierADD CONSTRAINT supplier_fk1FOREIGN KEY (s_nationkey) REFERENCES nation (n_nationkey);ALTER TABLE customerADD CONSTRAINT customer_fk1FOREIGN KEY (c_nationkey) REFERENCES nation (n_nationkey);ALTER TABLE partsuppADD CONSTRAINT partsupp_fk1FOREIGN KEY (ps_suppkey) REFERENCES supplier (s_suppkey);ALTER TABLE partsuppADD CONSTRAINT partsupp_fk2FOREIGN KEY (ps_partkey) REFERENCES part (p_partkey);ALTER TABLE ordersADD CONSTRAINT orders_fk1FOREIGN KEY (o_custkey) REFERENCES customer (c_custkey);ALTER TABLE lineitemADD CONSTRAINT lineitem_fk1FOREIGN KEY (l_orderkey) REFERENCES orders (o_orderkey);ALTER TABLE lineitemADD CONSTRAINT lineitem_fk2FOREIGN KEY (l_partkey, l_suppkey) REFERENCES partsupp (ps_partkey, ps_suppkey);COMMIT;
SQL

2. 执行这个新脚本

psql -d tpch -f pg_ri.sql

这一步可能会花一些时间,尤其是 lineitem 表比较大。

成功的话会看到很多:

ALTER TABLE

最后看到:

COMMIT

3. 收集统计信息

约束加完后执行:

psql -d tpch -c "VACUUM ANALYZE;"

4. 检查表和约束

psql -d tpch -c "\dt"
psql -d tpch -c "\d lineitem"

如果 \d lineitem 里能看到:

Primary key
Foreign-key constraints

说明约束已经加成功。

生成查询并修复查询语句

先执行下面这一整段,生成查询。

cd ~/TPCH/TPC-H/dbgenmkdir -p queries_pg results_baselinefor i in $(seq 1 22); doecho "Generating Q$i"DSS_QUERY=./queries ./qgen -s 1 $i > queries_pg/q$i.sql
done

1. 先修复已经生成的查询文件

在当前目录执行:

cd ~/TPCH/TPC-H/dbgenperl -pi -e "s/interval '([0-9]+)' day \(3\)/interval '\1 day'/g" queries_pg/*.sql

然后确认 Q1 已经改掉:

grep -n "interval" queries_pg/q1.sql

你应该看到类似:

l_shipdate <= date '1998-12-01' - interval '77 day'

2. 再跑 Q1

psql -d tpch -f queries_pg/q1.sql

如果 Q1 正常输出结果,就继续批量跑 22 条。


3. 批量跑 baseline

mkdir -p results_baselinefor i in $(seq 1 22); doecho "Running Q$i baseline"/usr/bin/time -f "Q$i elapsed: %e sec" \psql -d tpch -f queries_pg/q$i.sql \> results_baseline/q$i.out 2> results_baseline/q$i.time
done

查看耗时:

for i in $(seq 1 22); doecho -n "Q$i: "cat results_baseline/q$i.time
done

Q17和Q20卡住的处理情况

先加一组针对 TPC-H 常见连接列 + Q18/Q21 的索引,然后重新 ANALYZE,再单独重跑 Q18、Q21。

1. 创建索引脚本

进入目录:

cd ~/TPCH/TPC-H/dbgen

创建索引脚本:

cd ~/TPCH/TPC-H/dbgencat > pg_indexes_q17_q20.sql <<'SQL'
\set ON_ERROR_STOP on-- Q17: part 过滤 + lineitem 按 partkey/quantity 聚合
CREATE INDEX IF NOT EXISTS idx_part_brand_container_partkey
ON part (p_brand, p_container, p_partkey);CREATE INDEX IF NOT EXISTS idx_lineitem_partkey_quantity_price
ON lineitem (l_partkey, l_quantity, l_extendedprice);-- Q20: part name 前缀匹配 + partsupp + lineitem 日期数量聚合
CREATE INDEX IF NOT EXISTS idx_part_name_pattern_partkey
ON part (p_name text_pattern_ops, p_partkey);CREATE INDEX IF NOT EXISTS idx_partsupp_partkey_suppkey_availqty
ON partsupp (ps_partkey, ps_suppkey, ps_availqty);CREATE INDEX IF NOT EXISTS idx_lineitem_part_supp_shipdate_quantity
ON lineitem (l_partkey, l_suppkey, l_shipdate, l_quantity);CREATE INDEX IF NOT EXISTS idx_supplier_nation_supp_name
ON supplier (s_nationkey, s_suppkey, s_name);CREATE INDEX IF NOT EXISTS idx_nation_name_nationkey
ON nation (n_name, n_nationkey);VACUUM ANALYZE;
SQL
psql -d tpch -f pg_indexes_q17_q20.sql

建完索引后最好再执行一次

psql -d tpch -c "VACUUM ANALYZE;"

3. 重新跑 Q17 和 Q20

mkdir -p results_q17_q20/usr/bin/time -f "Q17 elapsed: %e sec" \psql -d tpch -f queries_pg/q17.sql \> results_q17_q20/q17.out \2> results_q17_q20/q17.time/usr/bin/time -f "Q20 elapsed: %e sec" \psql -d tpch -f queries_pg/q20.sql \> results_q17_q20/q20.out \2> results_q17_q20/q20.timecat results_q17_q20/q17.time
cat results_q17_q20/q20.time

4. 再跑一轮完整 indexed 结果

mkdir -p results_indexedfor i in $(seq 1 22); doecho "Running Q$i indexed"/usr/bin/time -f "Q$i elapsed: %e sec" \env PGOPTIONS='-c statement_timeout=30min' \psql -d tpch -f queries_pg/q$i.sql \> results_indexed/q$i.out \2> results_indexed/q$i.timeif [ $? -ne 0 ]; thenecho "Q$i TIMEOUT or ERROR" >> results_indexed/q$i.timefi
done

查看汇总:

for i in $(seq 1 22); doecho "===== Q$i ====="cat results_indexed/q$i.time
done

切换负载因子

强烈建议这样做:保留两个数据库,分别放 SF=1 和 SF=10。

比如:

tpch    -> SF=1
tpch10  -> SF=10

这样以后不用来回清空、导入,只需要连接不同数据库。

你现在已有 SF=1 数据库

你现在的 tpch 就保留为 SF=1:

psql -d tpch

SF=10 新建一个数据库:

createdb tpch10

如果已经存在并且你想重建:

dropdb tpch10
createdb tpch10

1. 生成 SF=10 数据到单独目录

cd ~/TPCH/TPC-H/dbgenmkdir -p data_sf10rm -f data_sf10/*.tbl./dbgen -s 10mv *.tbl data_sf10/cd data_sf10for f in *.tbl; dosed -i 's/|$//' "$f"
done

注意:这里会把当前目录下新生成的 .tbl 移动到 data_sf10/。你原来 SF=1 数据已经在 PostgreSQL 的 tpch 数据库里了,所以不受影响。

2. 生成查询

直接生成 SF=10 查询即可:

cd ~/TPCH/TPC-H/dbgenmkdir -p queries_pg_sf10for i in $(seq 1 22); doDSS_QUERY=./queries ./qgen -s 10 $i > queries_pg_sf10/q$i.sql
doneperl -pi -e "s/interval '([0-9]+)' day \(3\)/interval '\1 day'/g" queries_pg_sf10/*.sql

生成后检查:

ls -lh queries_pg_sf10/q1.sql
ls queries_pg_sf10

3. 在 tpch10 里建表

cd ~/TPCH/TPC-H/dbgenpsql -d tpch10 -f dss.ddl

如果提示表已存在,说明 tpch10 不是空的。可以重建:

dropdb tpch10
createdb tpch10
psql -d tpch10 -f dss.ddl

4. 导入 SF=10 数据

创建导入脚本:

cat > load_sf10.sql <<'SQL'
\set ON_ERROR_STOP on\copy region   from 'data_sf10/region.tbl'   with (format csv, delimiter '|');
\copy nation   from 'data_sf10/nation.tbl'   with (format csv, delimiter '|');
\copy supplier from 'data_sf10/supplier.tbl' with (format csv, delimiter '|');
\copy customer from 'data_sf10/customer.tbl' with (format csv, delimiter '|');
\copy part     from 'data_sf10/part.tbl'     with (format csv, delimiter '|');
\copy partsupp from 'data_sf10/partsupp.tbl' with (format csv, delimiter '|');
\copy orders   from 'data_sf10/orders.tbl'   with (format csv, delimiter '|');
\copy lineitem from 'data_sf10/lineitem.tbl' with (format csv, delimiter '|');
SQL

执行:

psql -d tpch10 -f load_sf10.sql

结果:

region    5
nation    25
supplier  100000
customer  1500000
part      2000000
partsupp  8000000
orders    15000000
lineitem  59986052

5. 给 tpch10 加主键外键

你之前的 PostgreSQL 版约束脚本 pg_ri.sql 可以复用:

psql -d tpch10 -f pg_ri.sql

加索引:

psql -d tpch10 -f pg_indexes_q17_q20.sql

然后收集统计信息:

psql -d tpch10 -c "VACUUM ANALYZE;"

运行:

mkdir -p results_indexed_sf10for i in $(seq 1 22); doecho "Running Q$i indexed"/usr/bin/time -f "Q$i elapsed: %e sec" \env PGOPTIONS='-c statement_timeout=30min' \psql -d tpch10 -f queries_pg/q$i.sql \> results_indexed/q$i.out \2> results_indexed/q$i.timeif [ $? -ne 0 ]; thenecho "Q$i TIMEOUT or ERROR" >> results_indexed/q$i.timefi
done

6. 查询时怎么区分 SF=1 和 SF=10

连接 SF=1:

psql -d tpch

连接 SF=10:

psql -d tpch10

跑 SF=1 查询:

psql -d tpch -f queries_pg/q1.sql

跑 SF=10 查询:

psql -d tpch10 -f queries_pg_sf10/q1.sql

6. 以后目录建议这样放

~/TPCH/TPC-H/dbgen/
├── data_sf10/             # SF=10 的 .tbl 数据文件
├── queries_pg/            # SF=1 查询
├── queries_pg_sf10/       # SF=10 查询
├── results_baseline/      # SF=1 结果
├── results_sf10_baseline/ # SF=10 结果
├── tpch 数据库             # SF=1
└── tpch10 数据库           # SF=10
http://www.zskr.cn/news/1481919.html

相关文章:

  • 深度解析:3种高效方法优化Windows 11性能的技术实践
  • 2026年6月做得好的粉末冶金模具厂商推荐,气流磨/扁平式汽粉机/冲压模具/合金模具,粉末冶金模具加工厂哪家专业 - 品牌推荐师
  • 茂名家庭教育指导师报名机构哪家好?首选中山优才教育正规授权入口(附联系方式) - 最新教育培训热点
  • 书匠策AI官网www.shujiangce.com:别再把论文写成“玄学“了!
  • Shizuku v13.6.0深度解析:Android系统权限管理的革命性突破
  • 终极指南:如何解决FanControl传感器识别问题并优化华硕主板兼容性
  • 2026年6月优质的铝型材踏步台公司推荐,铝型材框架/自动化铝型材/铝合金型材/欧标铝型材,铝型材踏步台实力厂家推荐 - 品牌推荐师
  • 2026年内部通讯软件排行:5款即时通讯软件私有化部署能力对比 - 小天互连即时通讯
  • 27届秋招提前看:只会传统后端,真的不够用了
  • WordPress主题终极指南:Argon-Theme让您的博客瞬间变身高颜值网站
  • 017、环境变量管理:settings.json 中的 env 配置、shell 继承与平台差异处理
  • Unlock Music音乐解锁工具:3分钟掌握跨平台音乐格式转换终极指南
  • 暗黑破坏神2存档编辑器d2s-editor:免费可视化修改工具完全指南
  • m3u8下载器全指南:轻松下载加密流媒体视频的Python解决方案
  • DINOv2自监督视觉特征学习终极指南:无需标签的强大视觉理解
  • 【Agent智能体20 | 构建AI工作流的技巧-组件级评估】
  • Windows上靠文本清单批量抓取并复制指定文件的C#小工具
  • 网络拓扑图绘制难题?这个零代码工具让你3分钟搞定专业图表
  • 7种音频格式自由转换:FlicFlac让你的Windows音频处理事半功倍
  • 【Agent智能体21 | 构建AI工作流的技巧-优化组件的常用方法】
  • 深入 Milvus 数据模型:Collection、Partition 与 Schema 设计最佳实践
  • 20254225 2025-2026-2 《Python程序设计》实验4报告
  • CPLD驱动ADC0804数据采集:状态机与硬件查表法实战解析
  • 3个智能功能彻底改变安卓应用安装体验:Windows平台APK安装器完全指南
  • 深度解析:如何高效掌握SCSI存储设备管理的核心技术工具
  • 2026年温州装修避坑调查:零增项模式如何规避常见陷阱 - 优家闲谈
  • 终极Boot Camp驱动自动化解决方案:3分钟搞定Mac Windows驱动部署
  • 软件过程与管理知识回顾2 -
  • 2026论文写作工具红黑榜:AI论文工具怎么选?一文讲透
  • CSLOL Manager:英雄联盟模组管理的一站式智能解决方案