关于优化:多维分析后台实践-2数据类型优化

42次阅读

共计 5569 个字符,预计需要花费 14 分钟才能阅读完成。

【摘要】
用实例、分步骤,具体解说多维分析(OLAP)的实现。点击理解多维分析后盾实际 2:数据类型优化

实际指标

本期指标是练习将数据库读出的数据,尽可能转换为有利于性能优化的数据类型,例如:小整数和浮点数。

实际的步骤:

1、筹备根底宽表:批改上期的代码,实现数据类型优化存为组表文件。

2、拜访根底宽表:批改上期的代码,在传入参数放弃不变的前提下,查问数据转换之后的组表文件,后果集也要返回原有的数据显示值。对于这个要求,SQL 是无奈实现传入参数和后果集的转换的,所以拜访宽表的代码以 SPL 为例。

本期样例宽表不变,仍然为 customer 表。从 Oracle 数据库中取出宽表数据的 SQL 语句是 select * from customer。执行后果如下图:

其中字段包含:

CUSTOMER_ID NUMBER(10,0), 客户编号

FIRST_NAME VARCHAR2(20), 名

LAST_NAME VARCHAR2(25), 姓

PHONE_NUMBER VARCHAR2(20), 电话号码

BEGIN_DATE DATE, 开户日期

JOB_ID VARCHAR2(10), 职业编号

JOB_TITLE VARCHAR2(32), 职业名称

BALANCE NUMBER(8,2), 余额

EMPLOYEE_ID NUMBER(4,0), 开户雇员编号

DEPARTMENT_ID NUMBER(4,0), 分支机构编号

DEPARTMENT_NAME VARCHAR2(32), 分支构造名称

FLAG1 CHAR(1), 标记 1

FLAG2 CHAR(1), 标记 2

FLAG3 CHAR(1), 标记 3

FLAG4 CHAR(1), 标记 4

FLAG5 CHAR(1), 标记 5

FLAG6 CHAR(1), 标记 6

FLAG7 CHAR(1), 标记 7

FLAG8 CHAR(1), 标记 8

多维分析计算的指标也不变,用上面 Oracle 的 SQL 语句示意:

select department_id,job_id,to_char(begin_date,’yyyymm’) begin_month ,sum(balance) sum,count(customer_id) count

from customer

where department_id in (10,20,50,60,70,80)

and job_id in (‘AD_VP’,’FI_MGR’,’AC_MGR’,’SA_MAN’,’SA_REP’)

and begin_date>=to_date(‘2002-01-01′,’yyyy-mm-dd’)

and begin_date<=to_date(‘2020-12-31′,’yyyy-mm-dd’)

and flag1=’1′ and flag8=’1′

group by department_id,job_id,to_char(begin_date,’yyyymm’)

筹备宽表

一、数值整数化

在 customer 表中有些字段自身就是整数,比方:CUSTOMER_ID、EMPLOYEE_ID、DEPARTMENT_ID。

解决办法:

l 如果从数据库中导出的是整型,就能够间接存储到组表中。

l 如果从数据库中导出的不是整型,要用类型转换函数强制转换为整型。

l 要留神尽量让整数值小于 65536,这样性能最好。如果原字段值被人为的转换成较大的整数,例如:所有的数值都加上了一个 100000,变成 100001、100002…,就要去掉后面的 1。

二、字符串整数化

FLAG1 到 FLAG8 是字符串,然而存储的仍然是整型数据,能够用类型转换函数转为整型。

JOB_ID 字段也是字符串,取值是 jobs 维表的主键,属于枚举类型。咱们能够用 jobs 表中的序号代替 JOB_ID 字段,实现整数化。

jobs 表构造和样例数据如下:

解决办法:

l 取出 jobs 中的 JOB_ID,排好序后形成一个序列 job。customer 宽表中减少 JOB_NUM 字段存储 JOB_ID 在序列 job 中的序号。

三、日期整数化

大多数状况下,日期型数据只是用来比拟,并不需要计算距离,所以也能够用小整数来存储。在多维分析计算中,依照年、月来计算的状况比拟常见。小整数化之后的日期,要求能很不便的把年、月拆分进去。

解决办法:

l 咱们能够计算出 BEGIN_DATE 字段值与一个日期终点的距离月数,乘以 100 后加上 BEGIN_DATE 的日值,来代替日期型数据存入组表。终点日期依据日期数据的特色来确定,值越大越好。

例如:咱们发现所有的 BEGIN_DATE 都在 2000 年之后,则能够确定日期终点为 2000-01-01。

确定日期终点后,就能够转化 customer 宽表中的 BEGIN_DATE 字段值了。例如:BEGIN_DATE 为 2010-11-20,先计算出和 2000-01-01 相差的整月数是 130,乘以 100 后加上日值 20 即可失去小整数 13020。

以 2000-01-01 为日期终点,BEGIN_DATE 小于 2050 年时,整数化之后的值都小于 65536。能够看到,在业务数据容许的前提下,日期终点尽量晚,能够更大程度避免出现宽表中的日期超出小整数范畴的状况。

四、无奈整数化的状况

必须用字符串示意的字段,如 FIRST_NAME、JOB_TITLE 等;

必须用浮点数示意的字段,如金额、折扣率等有小数局部的字段;

必须用字符串加整数一起示意的字段,如国内电话号码等。

解决办法:

l 放弃字段原值不动。

依据以上要求,改写 etl.dfx,从数据库中取出数据,类型转化后,生成组表文件,存储根底宽表。代码示例如下:

A1:连贯事后配置好的数据库 oracle,@l 是指取出字段名为小写。留神这里是小写字母 L。

B1:建设数据库游标,筹备取出 customer 表的数据。customer 是事实表,理论利用中个别都比拟大,所以用游标形式,防止内存溢出。游标的 @d 选项是将 oracle 的 numeric 型数据转换成 double 型数据,而非 decimal 型数据。decimal 型数据在 java 中的性能较差。

A2:从数据库中读 jobs 表,只读取 JOB_ID 字段并排序。jobs 是维表,个别都比拟小,所以间接读入到内存中。

B2:将 A2 的数据存储成集文件,待前面应用。

A3:将 A2 转化为序列。

B3:定义日期 2000-01-01。

A4:用 new 函数定义三种计算。

1、CUSTOMER_ID 等确定是整数的数值,从 double 或者 string 转换为 int。办法是间接用 int 函数做类型转换。留神 int 不能大于 2147483647,对于数据量超过这个数值的事实表,序号主键要用 long 型。

2、将 JOB_ID 从字符串转化为整数,进步计算性能。办法是用 pos 函数找到 job_id 在 A3 中的序号,定义为 JOB_NUM 字段。

3、用 interval 计算 begin_date 和 2000-01-01 之间相差的整月数,乘以 100 加上 begin_date 的日值,用 int 转换为整数存储为新的 begin_date。

A5:定义列存组表文件。字段名和 A4 完全一致。

A6:边计算游标 A4,边输入到组表文件中。

B6:敞开组表文件和数据库连贯。

数据量为一千万,导出组表文件约 344MB。和第一期未做数据类型优化的文件比拟如下:

从上表能够看出,实现数据类型优化之后,文件大小缩小了 12%(49M)。文件变小,能缩小磁盘读取数据量,无效进步性能。

拜访宽表

如上所述,后盾组表的很多字段曾经优化转换,没有方法用原来的 SQL 进行查问了。咱们采纳执行脚本的形式,提交过滤条件、分组字段等参数,后盾将参数值转换成优化后的数据类型,再对组表进行计算。这样做,能够保障通用多维分析前端传入的参数放弃不变。最初,计算结果也须要转换为对应的显示值。

例如:传入的参数 flag1=’1’,须要转换为 flag1=1;计算结果中的 job_num 和 begin_date,还要从整数转换为字符串 job_id 和日期。

为了实现这个计算,要先在节点服务器主目录中编写 init.dfx 文件,事后加载全局变量 job,用于后续的转换计算。

init.dfx 代码如下:

A1:取出集文件中的数据,@i 示意只有一列时读成序列。

B1:存入全局变量 job。

写好的 init.dfx 要放入节点机主目录,启动或重启节点机时会被主动调用。

依照数据类型优化要求改写 olap-spl.dfx,用 SPL 代码拜访宽表并进行过滤和分组汇总计算。

定义网格参数,将文件名、部门编号、工作编号、标记位、日期范畴、分组字段、聚合表达式别离传入。

参数设置窗口如下,和第一期完全一致:

参数值样例:

filename=”data/customer.ctx”

arg_department_id =”10,20,50,60,70,80″

arg_job_id=”AD_VP,FI_MGR,AC_MGR,SA_MAN,SA_REP”

arg_begin_date_min = “2002-01-01”

arg_begin_date_max =”2020-12-31″

arg_flag =”flag1==\”1\”&& flag8==\”1\” “

group=”department_id,job_id,begin_yearmonth”

aggregate=”sum(balance):sum,count(customer_id):count”

阐明:group 中如果是 begin_date 则依照日期分组,如果是 begin_yearmonth 则依照年月分组。对于多维分析前端来说,能够认为有两个字段。

SPL 代码示例如下:

A1:关上组表对象。B1:定义终点日期 2000-01-01 用于参数和后果中的日期值转换。

A2、B2:将传入日期参数依照后面介绍的办法转化为整数。

A3:将传入的逗号分隔字符串 job_id 转换为在全局变量 job 序列中的地位,也就是 job_num 整数序列。

B3:将传入的逗号分隔字符串 department_id 用 int 函数转换为整数序列。

A4:将传入的 flag 条件中的双引号去掉,变为整数条件。

B4:将传入的分组字段中的 job_id 替换为 job_num。

A5:将传入的分组字段中的 begin_yearmonth,替换为 begin_date\100。begin_date 的字段值除以 100 取整,就是理论日期和终点日期相差的月数。

A6:定义带过滤条件的游标。

A7:对游标计算小后果集分组汇总。

A8:将 A7 后果的字段名造成序列。

B8:字段名中如果有 job_num,就替换成转换语句。语句的作用是:将分组后果中的 job_num 转换为 job_id。

A9:字段名中如果有 begin_yearmonth,替换为转换语句,作用是:将分组字段中的月差值 begin_yearmonth 从整数转化为 yyyymm。

A10:字段名中如果有 begin_date,替换为转换语句,作用是:将分组字段中的整数化日期值转换为日期型。

A11:将替换之后的 A8 从新用逗号连接成字符串,并对 A7 循环计算,实现字段类型和显示值的转换。

A12:返回 A11 后果集。

执行后果如下图:

olap-spl.dfx 编写好之后,能够在多维分析中作为存储过程调用,Java 代码和第一期雷同。如下:

public void testOlapServer(){

Connection con = null;

java.sql.PreparedStatement st;

try{

// 建设连贯

Class.forName(“com.esproc.jdbc.InternalDriver”);

// 依据 url 获取连贯

con= DriverManager.getConnection(“jdbc:esproc:local://?onlyServer=true&sqlfirst=plus”);

// 调用存储过程,其中 olap-spl 是 dfx 的文件名

st =con.prepareCall(“call olap-spl(?,?,?,?,?,?,?,?)”);

st.setObject(1, “data/customer.ctx”);//arg_filename

st.setObject(2, “10,20,50,60,70,80”);//arg_department_id

st.setObject(3, “AD_VP,FI_MGR,AC_MGR,SA_MAN,SA_REP”);//arg_job_id

st.setObject(4, “2002-01-01”);//arg_begin_date_min

st.setObject(5, “2020-12-31”);//arg_begin_date_max

st.setObject(6, “flag1==\”1\”&& flag8==\”1\” “);//arg_flag

st.setObject(7, “department_id,job_id,begin_yearmonth”);//arg_group

st.setObject(8, “sum(balance):sum,count(customer_id):count”);//arg_aggregate

// 执行存储过程

st.execute();

// 获取后果集

ResultSet rs = st.getResultSet();

// 持续处理结果集,将后果集展示进去

}

catch(Exception e){

out.println(e);

}

finally{

// 敞开连贯

if (con!=null) {

try {con.close();}

catch(Exception e) {out.println(e); }

}

}

}

Java 代码加上后盾计算返回后果总的执行工夫,和第一期比拟如下:

如上期所述,表中的执行工夫硬件配置相干,其相对数值并不重要。重要的是,通过上表的比照能够看出,数据类型优化无效进步了计算性能。

正文完
 0