TPC-H测试提供了8张表,最近做这个测试,记录下过程中的关键点备忘。

  • 1.整体理解TPC-H 8张表
  • 2.建立主外键约束后测试22条SQL
  • 3.分区表改造,确认分区字段
  • 4.重新测试22条SQL
  • 5.In-Memory效果测试
  • 6.大表并行度设置

1.整体理解TPC-H 8张表

TPC-H 属于 雪花型查询(Snowflake Schema)。

  • 雪花型结构,是在星型查询的基础上,维度表进一步规范化,形成多层级的关联关系。

TPC-H 的 8 张表之间的关系如下:

事实表:

  • LINEITEM:记录订单明细信息。主键为l_orderkey,l_linenumber
  • ORDERS:记录订单信息。主键为o_orderkey

维度表:

  • PART:记录零件信息。主键为p_partkey
  • SUPPLIER:记录供应商信息。主键为s_suppkey
  • PARTSUPP:记录零件与供应商的关系。主键为ps_partkey
  • CUSTOMER:记录客户信息。主键为c_custkey
  • NATION:记录国家信息。主键为n_nationkey
  • REGION:记录地区信息。主键为r_regionkey

这些表之间的关系是多层级的,例如:

  • LINEITEM 关联到 PARTSUPP,PARTSUPP 关联到 PART 和 SUPPLIER。
  • SUPPLIER 关联到 NATION,NATION 关联到 REGION。

这种多层级的规范化结构符合 雪花型查询 的特点,下图ER图来源于官方tpc-h压缩包中的specification说明文档内容:

2.建立主外键约束后测试22条SQL

原环境未建立任何主键和索引,可以先参考dss.ri修改创建必要的主键和外键约束,我依照本次测试环境微调如下:

-- 1.主键约束(显式指定索引表空间tbs_alfred_index):
-- For table REGION
ALTER TABLE REGION ADD PRIMARY KEY (R_REGIONKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table NATION
ALTER TABLE NATION ADD PRIMARY KEY (N_NATIONKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table PART
ALTER TABLE PART ADD PRIMARY KEY (P_PARTKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table SUPPLIER
ALTER TABLE SUPPLIER ADD PRIMARY KEY (S_SUPPKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table PARTSUPP
ALTER TABLE PARTSUPP ADD PRIMARY KEY (PS_PARTKEY, PS_SUPPKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table CUSTOMER
ALTER TABLE CUSTOMER ADD PRIMARY KEY (C_CUSTKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table ORDERS
ALTER TABLE ORDERS ADD PRIMARY KEY (O_ORDERKEY) USING INDEX TABLESPACE tbs_alfred_index;
-- For table LINEITEM
ALTER TABLE LINEITEM ADD PRIMARY KEY (L_ORDERKEY, L_LINENUMBER) USING INDEX TABLESPACE tbs_alfred_index; -- 2.外键约束:
-- For table NATION
ALTER TABLE NATION
ADD CONSTRAINT NATION_FK1 FOREIGN KEY (N_REGIONKEY) REFERENCES REGION;
-- For table SUPPLIER
ALTER TABLE SUPPLIER
ADD CONSTRAINT SUPPLIER_FK1 FOREIGN KEY (S_NATIONKEY) references NATION;
-- For table CUSTOMER
ALTER TABLE CUSTOMER
ADD CONSTRAINT CUSTOMER_FK1 FOREIGN KEY (C_NATIONKEY) references NATION;
-- For table PARTSUPP
ALTER TABLE PARTSUPP
ADD CONSTRAINT PARTSUPP_FK1 FOREIGN KEY (PS_SUPPKEY) references SUPPLIER;
ALTER TABLE PARTSUPP
ADD CONSTRAINT PARTSUPP_FK2 FOREIGN KEY (PS_PARTKEY) references PART;
-- For table ORDERS
ALTER TABLE ORDERS
ADD CONSTRAINT ORDERS_FK1 FOREIGN KEY (O_CUSTKEY) references CUSTOMER;
-- For table LINEITEM
ALTER TABLE LINEITEM
ADD CONSTRAINT LINEITEM_FK1 FOREIGN KEY (L_ORDERKEY) references ORDERS;
ALTER TABLE LINEITEM
ADD CONSTRAINT LINEITEM_FK2 FOREIGN KEY (L_PARTKEY,L_SUPPKEY) references PARTSUPP;

这些其实并没有针对性优化,效果反而不如之前。

比如其中的query5,就因为走错执行计划,比之前什么都没有的情况还要慢很多倍。

3.分区表改造,确认分区字段

对最大的两张事实表做分区改造。

简单浏览了相关SQL,虽然查询的数据很多,但也都是对日期有一定过滤的,因此先尝试简单的按时间range分区:

  • LINEITEM:分区字段:l_shipdate 。
  • ORDERS:分区字段:o_orderdate。

目前两张表分区字段的数据存放都是7年:1992~1998。可以验证:

--验证数据(选做,我这里已经帮大家验证过脚本生成的固定是这些年的数据)
sqlplus tpch/tpch@alfred select to_char(l_shipdate, 'yyyy'), count(*) from LINEITEM group by to_char(l_shipdate, 'yyyy') order by 1; select to_char(o_orderdate, 'yyyy'), count(*) from ORDERS group by to_char(o_orderdate, 'yyyy') order by 1;

两张事实表的分区语句参考,为了考虑灵活性,我选择了interval分区,并显示指定了当前存在数据的年份:

--drop table ORDERS purge;
--ALTER TABLE LINEITEM DROP CONSTRAINT LINEITEM_FK1;
CREATE TABLE ORDERS (O_ORDERKEY INTEGER NOT NULL,
O_CUSTKEY INTEGER NOT NULL,
O_ORDERSTATUS CHAR(1) NOT NULL,
O_TOTALPRICE DECIMAL(15,2) NOT NULL,
O_ORDERDATE DATE NOT NULL,
O_ORDERPRIORITY CHAR(15) NOT NULL,
O_CLERK CHAR(15) NOT NULL,
O_SHIPPRIORITY INTEGER NOT NULL,
O_COMMENT VARCHAR(79) NOT NULL)
PARTITION BY RANGE (o_orderdate)
INTERVAL (NUMTOYMINTERVAL(1, 'YEAR')) -- 一年一个分区
(
PARTITION p_1992 VALUES LESS THAN (TO_DATE('1993-01-01', 'YYYY-MM-DD')),
PARTITION p_1993 VALUES LESS THAN (TO_DATE('1994-01-01', 'YYYY-MM-DD')),
PARTITION p_1994 VALUES LESS THAN (TO_DATE('1995-01-01', 'YYYY-MM-DD')),
PARTITION p_1995 VALUES LESS THAN (TO_DATE('1996-01-01', 'YYYY-MM-DD')),
PARTITION p_1996 VALUES LESS THAN (TO_DATE('1997-01-01', 'YYYY-MM-DD')),
PARTITION p_1997 VALUES LESS THAN (TO_DATE('1998-01-01', 'YYYY-MM-DD')),
PARTITION p_1998 VALUES LESS THAN (TO_DATE('1999-01-01', 'YYYY-MM-DD'))
); --drop table LINEITEM purge;
CREATE TABLE LINEITEM (L_ORDERKEY INTEGER NOT NULL,
L_PARTKEY INTEGER NOT NULL,
L_SUPPKEY INTEGER NOT NULL,
L_LINENUMBER INTEGER NOT NULL,
L_QUANTITY DECIMAL(15,2) NOT NULL,
L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,
L_DISCOUNT DECIMAL(15,2) NOT NULL,
L_TAX DECIMAL(15,2) NOT NULL,
L_RETURNFLAG CHAR(1) NOT NULL,
L_LINESTATUS CHAR(1) NOT NULL,
L_SHIPDATE DATE NOT NULL,
L_COMMITDATE DATE NOT NULL,
L_RECEIPTDATE DATE NOT NULL,
L_SHIPINSTRUCT CHAR(25) NOT NULL,
L_SHIPMODE CHAR(10) NOT NULL,
L_COMMENT VARCHAR(44) NOT NULL)
PARTITION BY RANGE (l_shipdate)
INTERVAL (NUMTOYMINTERVAL(1, 'YEAR')) -- 一年一个分区
(
PARTITION p_1992 VALUES LESS THAN (TO_DATE('1993-01-01', 'YYYY-MM-DD')),
PARTITION p_1993 VALUES LESS THAN (TO_DATE('1994-01-01', 'YYYY-MM-DD')),
PARTITION p_1994 VALUES LESS THAN (TO_DATE('1995-01-01', 'YYYY-MM-DD')),
PARTITION p_1995 VALUES LESS THAN (TO_DATE('1996-01-01', 'YYYY-MM-DD')),
PARTITION p_1996 VALUES LESS THAN (TO_DATE('1997-01-01', 'YYYY-MM-DD')),
PARTITION p_1997 VALUES LESS THAN (TO_DATE('1998-01-01', 'YYYY-MM-DD')),
PARTITION p_1998 VALUES LESS THAN (TO_DATE('1999-01-01', 'YYYY-MM-DD'))
);

sqlldr重新导入数据

还是使用之前的导入方法,重新导入这两张表数据到新建的分区表中。

# 7.ORDERS
sqlldr userid=tpch/tpch@alfred control=ORDERS.ctl log=ORDERS.log bad=ORDERS.bad direct=true # 8.LINEITEM
sqlldr userid=tpch/tpch@alfred control=LINEITEM.ctl log=LINEITEM.log bad=LINEITEM.bad direct=true

记得维护好主键和外键约束。

这里也给出主外键的删除约束语句,以备测试期间的不时之需。

--删除所有主键和外键?
-- 1.删除主键约束:
-- For table REGION
ALTER TABLE REGION drop PRIMARY KEY ;
-- For table NATION
ALTER TABLE NATION drop PRIMARY KEY ;
-- For table PART
ALTER TABLE PART drop PRIMARY KEY ;
-- For table SUPPLIER
ALTER TABLE SUPPLIER drop PRIMARY KEY ;
-- For table PARTSUPP
ALTER TABLE PARTSUPP drop PRIMARY KEY ;
-- For table CUSTOMER
ALTER TABLE CUSTOMER drop PRIMARY KEY ;
-- For table ORDERS
ALTER TABLE ORDERS drop PRIMARY KEY ;
-- For table LINEITEM
ALTER TABLE LINEITEM drop PRIMARY KEY ; -- 2.删除外键约束:
-- For table NATION
ALTER TABLE NATION drop CONSTRAINT NATION_FK1; -- For table SUPPLIER
ALTER TABLE SUPPLIER drop CONSTRAINT SUPPLIER_FK1; -- For table CUSTOMER
ALTER TABLE CUSTOMER drop CONSTRAINT CUSTOMER_FK1; -- For table PARTSUPP
ALTER TABLE PARTSUPP drop CONSTRAINT PARTSUPP_FK1; ALTER TABLE PARTSUPP drop CONSTRAINT PARTSUPP_FK2; -- For table ORDERS
ALTER TABLE ORDERS drop CONSTRAINT ORDERS_FK1; -- For table LINEITEM
ALTER TABLE LINEITEM drop CONSTRAINT LINEITEM_FK1; ALTER TABLE LINEITEM drop CONSTRAINT LINEITEM_FK2;

4.重新测试22条SQL

尝试了一些分析索引,比如连接条件的字段建立索引,重新测试整体效果并不好,个别SQL有效,但对整体并起不到啥作用,甚至会更差,最后我都删掉或者invisible了,因此我个人是不太建议折腾这方面,但你如果是优化高手,或者研究时间很充裕的话,可以试试看。

5.In-Memory效果测试

嗯,我这时间有限,怎么办呢,来试试大名鼎鼎的In-Memory吧,上篇文章《优化利器In-Memory开启和效果》已经简单介绍了下这个特性,这里正好用TPC-H的压力测试场景来验证下In-Memory的威力,总之优化原则就是简单高效。

ALTER TABLE REGION inmemory;
ALTER TABLE NATION inmemory;
ALTER TABLE PART inmemory;
ALTER TABLE SUPPLIER inmemory;
ALTER TABLE PARTSUPP inmemory;
ALTER TABLE CUSTOMER inmemory;
ALTER TABLE ORDERS inmemory;
ALTER TABLE LINEITEM inmemory;

注意,设置完inmemory属性可不算完,要想用到,还需确认其发布成功:

SELECT OWNER, SEGMENT_NAME NAME,
POPULATE_STATUS STATUS
FROM V$IM_SEGMENTS; --或者干脆查所有字段,更详细的展示:
SELECT * FROM V$IM_SEGMENTS order by 2;

这里起初遇到一些问题,内存不太够,部分分区发布时会报错:out of memory..

我没有使用更高的压缩方式,临时申请了一些内存资源再次尝试,还是报错。

明明按当前压缩比例计算是够用的,究竟咋回事呢,原来默认inmemory area只有70%的空间可用,可以通过查看看到:【1MB的Pool默认只有70%,剩下30%基本都给了64k的Pool】

select * from v$inmemory_area;

这里请教了同事@萧宇,快速得知是有个隐藏参数_inmemory_64k_percent控制inmemory的pool分布比例,默认值就是30:

NAME                                DESCRIPTION                                                        VALUE
----------------------------------- ------------------------------------------------------------------ ------------------------------
_inmemory_64k_percent percentage of in-memory area for 64k pools 30 Elapsed: 00:00:00.01

注意,生产环境自然不建议修改隐藏参数!

但我这里是测试,资源实在是有限,所以在观察目前测试64k的pool其实用不了太多,就直接把它改成了5:

alter system set "_inmemory_64k_percent"=5 scope=spfile;

需要重启数据库生效。

发布的时候,顺便dstat监控下I/O情况,调整内存后,I/O也比以前好一些了?

不重要,只要还走I/O,就一定慢。这跟数据库能力无关,硬件的I/O瓶颈就在那里。

发布的脚本示例:

--vi im_init.sh
select count(*) from REGION;
select count(*) from NATION;
select count(*) from PART;
select count(*) from SUPPLIER;
select count(*) from PARTSUPP;
select count(*) from CUSTOMER;
select count(*) from ORDERS;
select count(*) from LINEITEM;

注意:这些SQL查询完成,不一定就代表发布也完成了,实际观察是会有个过程的,还是要监控等待发布状态确定是完成,然后再执行TPC-H的22条SQL。

SELECT * FROM V$IM_SEGMENTS order by 2;
select * from v$inmemory_area;

终于确认本次全部发布成功,没有任何OOM的报错。

再次跑22条SQL看效果,大部分SQL都很快,秒级别,但是个别慢的是用到了temp表空间,这还是受限于硬件的I/O,不过这也比之前好很多了。

同时,alert日志也报出ORA-04036: 实例或 PDB 使用的 PGA 内存超出 PGA_AGGREGATE_LIMIT。,嗯,PGA又尽可能的给扩了扩。

6.大表并行度设置

本次测试环境只有4个OCPU,也就是8个vCPU;

并行不能开太大,就针对两张大表,设置了表级别的并行度为8,效果提升明显。

alter table LINEITEM parallel(degree 8);
alter table ORDERS parallel(degree 8);

之前个别慢的SQL也都提升到了秒级别,虽然具体测试数据不方便放出来,但可以说结论是本次整体测试执行效果是达到甚至超过了预期。

干脆将其他几张中表也进行设置:

alter table PARTSUPP parallel(degree 4);
alter table PART parallel(degree 4);
alter table SUPPLIER parallel(degree 4);
alter table CUSTOMER parallel(degree 4);

测试结果又进一步提升了。

当然,如果硬件资源充足,进一步加大并行度,理论上还会有更进一步的性能提升,大家如果有条件的话,可以试试看。

TPC-H 研究和优化尝试的更多相关文章

  1. 转:浅谈关于b、h标签的优化技巧

    <b>标签优化 <b>标签是一种加粗标记,作用就是加粗文章中的关键词,对于文章中重要的关键词加粗起到有利于用户阅读的作用.<b>标签的使用对于优化的作用是非常大的, ...

  2. 研究Mysql优化得出一些建设性的方案

    博客出自:http://blog.csdn.net/liuxian13183,转载注明出处! All Rights Reserved ! 熟悉网络请求路径,网址经过浏览器的URL验证,是否正确证书是否 ...

  3. 一次WEB前端优化尝试

    今天对自己做的项目中的一个设计器界面加载速度上进行了优化,因为页面在加载的时候,感觉有点慢.首先,我用firefox的yslow和chrome的pagespeed进行了测试,效果如下,分数有点不同,但 ...

  4. Java进阶专题(二十六) 数据库原理研究与优化

    前言 在一个大数据量的系统中,这些数据的存储.处理.搜索是一个非常棘手的问题. 比如存储问题:单台服务器的存储能力及数据处理能力都是有限的, 因此需要增加服务器, 搭建集群来存储海量数据. 读写性能问 ...

  5. Oracle的update语句优化研究

    最近研究sql优化,以下文章转自互联网: 1.     语法 单表:UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值 如:update t_join_situation s ...

  6. uitableview 优化

    1. http://www.cocoachina.com/ios/20150602/11968.html 最近在微博上看到一个很好的开源项目VVeboTableViewDemo,是关于如何优化UITa ...

  7. TOP100summit:【分享实录-QQ空间】10亿级直播背后的技术优化

    本篇文章内容来自2016年TOP100summit QQ空间客户端研发总监王辉的案例分享.编辑:Cynthia 王辉:腾讯SNG社交平台部研发总监.腾讯QQ空间移动客户端技术负责人高级工程师.09年起 ...

  8. 机器指令翻译成 JavaScript —— No.6 深度优化

    第一篇 中我们曾提到,JavaScript 最终还得经过浏览器来解析.因此可以把一些优化工作,交给脚本引擎来完成. 现代浏览器的优化能力确实很强,但是,运行时的优化终归是有限的.如果能在事先实现,则可 ...

  9. (转)as3效率优化

    1.改进算法无论对于那一种程序,好的算法总是非常重要的,而且能够极大地提高程序性能,所以任何性能的优化第一步就是从算法或者说程序逻辑的优化开始,检查自己的程序是否有多余的运算,是否在没有必要的时候做了 ...

  10. 访问日志IO性能优化

    在高并发量的场景下磁盘IO往往是性能的瓶颈所在,访问日志涉及到频繁的写操作,所以这部分要尽可能地优化,不然将拖累系统的整体性能.针对文件记录及数据库记录两种方式可以有以下措施提高写性能, l 避免频繁 ...

随机推荐

  1. resttemplate 调用https 出错 unable to find valid certification path to requested target

    resttemplate 调用https使用下面代码: @Bean @Primary public RestTemplate restTemplate(ClientHttpRequestFactory ...

  2. 永久告别mac屏幕涂层脱落

    转载:https://www.feng.com/post/11380203 我从2011年开始使用Mac book pro电脑,到现在的2016款已经是第三台了,我从来都不会被涂层脱落这个问题困扰,我 ...

  3. 龙哥量化:通达信分时均线在5分钟K线图上显示

    代写技术指标.量化策略,微信:Long622889 龙哥QQ:591438821 T1:=DAY<>REF(DAY,1);T2:=BARSLAST(T1)+1;JX:SUM(AMO,T2) ...

  4. Qt安卓开发经验021-030

    关于权限设置,在早期的安卓版本,所有权限都写在全局配置文件AndroidManifest.xml中,这种叫安装时权限,就是安装的时候告诉安卓系统当前app需要哪些权限.大概从安卓6开始,部分权限需要动 ...

  5. [转]ubuntu20.04使用dev-sidecar找不到安装证书

    火狐.chrome等浏览器不走系统证书,火狐.谷歌浏览器必须在浏览器上安装证书 然后死活找不到证书,搜索了整个目录也没有. 原来是我的显示隐藏文件没打开.打开目录的"显示隐藏文件" ...

  6. IM消息ID技术专题(六):深度解密滴滴的高性能ID生成器(Tinyid)

    1.引言 在中大型IM系统中,聊天消息的唯一ID生成策略是个很重要的技术点.不夸张的说,聊天消息ID贯穿了整个聊天生命周期的几乎每一个算法.逻辑和过程,ID生成策略的好坏有可能直接决定系统在某些技术点 ...

  7. 2022 年数据科学研究综述:重点介绍 ML、DL、NLP 等

    2022 年数据科学研究综述:重点介绍 ML.DL.NLP 等 当我们在 2022 年底临近时,我对许多著名研究小组完成的所有惊人工作感到振奋,他们将 AI.机器学习.深度学习和 NLP 的状态扩展到 ...

  8. WPF 设置DataGrid 选中的背景色和前景色

    <DataGrid > <DataGrid.CellStyle> <Style TargetType="DataGridCell"> <S ...

  9. 史上最强Dubbo面试28题答案详解

    1.Dubbo是什么? Dubbo 是一个分布式.高性能.透明化的 RPC 服务框架,提供服务自动注册.自动发现等高效服务治理方案, 可以和 Spring 框架无缝集成. RPC 指的是远程调用协议, ...

  10. w3cschool-Struts2 概述

    Struts2 概述 Struts2 是目前较为普及和成熟的基于MVC设计模式的web应用程序框架,它不仅仅是Struts1 的升级版本,更是一个全新的Struts架构.最初,是以WebWork框架和 ...