DQL 实践 :元数据与语法

一、 准备数据

我们选用1G规模的TPCH数据来实践DQL查询,TPCH生成如下8个表的数据文件(*.tbl)

..

文件内容是文本格式,第一行是字段名,之后是数据行,行内数据以|分隔,如part表:

..

DQL查询的数据表,需要以SPL的组表文件格式(*.ctx)存储,用以下的SPL脚本把文本文件转换成组表文件:


A

B


1

E:\TPCH\



2

1024

supplier

#S_SUPPKEY,S_NAME,S_ADDRESS,S_NATIONKEY,S_PHONE,S_ACCTBAL,S_COMMENT

3

1048576

partsupp

#PS_PARTKEY,#PS_SUPPKEY,PS_AVAILQTY,PS_SUPPLYCOST,PS_COMMENT

4

1048576

part

#P_PARTKEY,P_NAME,P_MFGR,P_BRAND,P_TYPE,P_SIZE,P_CONTAINER,P_RETAILPRICE,P_COMMENT

5

1048576

orders

#O_ORDERKEY,O_CUSTKEY,O_ORDERSTATUS,O_TOTALPRICE,O_ORDERDATE,O_ORDERPRIORITY,O_CLERK,O_SHIPPRIORITY,O_COMMENT

6

1048576

lineitem

#L_ORDERKEY,#L_LINENUMBER,L_PARTKEY,L_SUPPKEY,L_QUANTITY,L_EXTENDEDPRICE,L_DISCOUNT,L_TAX,L_RETURNFLAG,L_LINESTATUS,L_SHIPDATE,L_COMMITDATE,L_RECEIPTDATE,L_SHIPINSTRUCT,L_SHIPMODE,L_COMMENT

7

1048576

customer

#C_CUSTKEY,C_NAME,C_ADDRESS,C_NATIONKEY,C_PHONE,C_ACCTBAL,C_MKTSEGMENT,C_COMMENT

8

1024

nation

#N_NATIONKEY,N_NAME,N_REGIONKEY,N_COMMENT

9

1024

region

#R_REGIONKEY,R_NAME,R_COMMENT

10

=create(size,tblName,fields).record([A2:C9])

11

for A10

=file(A1/A11.tblName/".tbl").import@t(;,"|")

12


=file(A1/A11.tblName/".ctx").create(${A11.fields};;A11.size)

13


>B12.append(B11.cursor()),B12.close()

2~9行定义8个表,A列定义组表区块大小,数据量很小的表设置区块为1KB,其它表设置为1MBB列为表名;C列为字段名,#开头的字段是主键维字段;

把这8个表的信息写入A10的序表中;

111213行逐个创建组表,把文本数据写入组表文件。

二、 创建DQL元数据文件

创建虚表

打开DQL设计器,新建元数据文件:

..

添加表,选择上面生成的组表customer.ctx文件,看到字段、主键将自动识别出来:

..

用同样的方法把剩余的表都加载进来,然后元数据文件保存为TPCH.glmd

..

customernationpartregionsupplier这几个表设置“Load into memory”,DQL要求维表要预先加载入内存(虚表本身并不要求):

..

设置DQL

引入虚表

切换到DQL标签下,这时DQL下还没有任何表:

..

点击菜单Tool -> Generate table from pseudo table

..

选出刚才加载的所有虚表:

..

DQL表创建成功,自动识别出了主键、数据类型:

..

对表名、字段名稍作调整,表名首字母改为大写,字段名去掉“C_”等前缀:

..

创建逻辑维表:年、月、日期

查询数据时,按照年、月、日期分组很常见,所以需要对这些维要预定义出来,在工具栏中点击添加逻辑表的按钮,表名设置为Year,再添加字段,字段名也用Year,设置为主键,数据类型选择整数类型:

..

同样步骤添加月维表,月维的字段值包含年份信息,也是整数类型,比如202308,表示20238月:

..

其它表中的日期字段大多是日期类型,所以日期就不用类似20230815这样的整数类型了,设置成日期类型:

..

设置表间关联关系

选择Lineitem表,切换到外键标签页,添加外键,然后设置每个外键的关联关系。如fk2外键,用LineitemPARTKEY字段关联Part维表的主键PARTKEY字段:

..

所有表设置好外键关联后,切换到View标签页,可以看到中间位置列出所有分类维,DQL表列两边,每个表通过连线连接它涉及的所有分类维:

..

和常规ER图一样,都能表达各表的关联关系,但DQL通过引入分类维概念,形成这种总线形式的关系图。

SupplierCustomer表通过外键关联到Nation表,Nation表就是一个维表,Nation就是一个分类维,三个表中的NATIONKEY字段存储的都是Nation维的值。

维表计算时要被随机访问,DQL(底层的SPL)要求将维表预先加载入内存。维表一般数据量较小,可以被装入内存。

设置维及维层

切换到Dim and level标签页,年、月、日期这三个时间维需要设置一下:

年维的时间维类型是Year,格式化表达式?1表示年份;

月维的时间维类型是Year month,格式化表达式中年份?1*100,加上月份?2,就形成了形如202308的月维值了;

日期维的时间维类型是Year month day,用SPL函数date(year,month,day)算出日期类型的日维值;

日期维通过层函数,能计算出月维、年维。比如计算月维的层函数year(?)*100+month(?),其中?代表当前的日期维值,用SPLmonth(date)函数获得日期的月份、用year(date)函数获得日期的年份。

..

同理,在月维中用层函数int(?/100)也能计算出年维:

..

保存TPCH.glmd,基于这个元数据文件,就可以做DQL查询了;之后把它部署到DQL服务器上,就能以JDBC方式对外提供查询服务。

三、测试DQL查询

DQL元数据文件如上制作完成后,可以先用Tool –> DQL query测试一下DQL查询:

..

DQL示例1

手写个最简单的DQL,然后点击执行,看到下方查询出数据了:

..

DQL示例2—广义字段

写个更复杂的,有Orders表的直接字段orderkey

通过日期维字段orderdate的层函数year查询出年维,也就是订单年份:orderdate#year

通过custkey这个外键字段查询客户名称:custkey.name,这个广义字段实际查询时,会自动关联Customer表;

还可以有更多层的广义字段查询,custkey.nationkey.regionkey.name,查询出订单客户国家地区名称,涉及到的OrdersCustomerNationRegion四个表会自动关联:

SELECT

   orderkey,

   orderdate#year orderyear,

   custkey.name custname,

   custkey.nationkey.regionkey.name regionname

FROM Orders

DQL示例3—按维/维层分组汇总

Lineitem表中按照月份、供应商维统计最小折扣,总数量,by子句中指定按照shipdate的月份、suppkey分组:

SELECT

   MIN(discount) ,

   SUM(quantity)

ON

   month,

   supplier

FROM Lineitem

   BY shipdate#month, suppkey

分组的月维值,是用层函数month从日期维shipdate计算出来,层函数month也可以省略掉,DQL会自动找到合适层函数计算,BY子句可以精简为:BY shipdate, suppkey

DQL示例4—()表按同维对齐汇总

Supplier表和Customer表不直接相关联,但它们也可能按照相同的维度一起分组汇总,如按照国家统计供应商数、客户数:

SELECT

   COUNT(s.name) suppNum,

   COUNT(c.name) custNum

ON

   nation

FROM

   Supplier s BY nationkey

   UNION

   Customer c BY nationkey

DQL示例5—明细条件/过滤汇总/结果排序/取前N

基于示例4,增加一些常用的查询功能:

明细条件:WHERE nation>5

过滤汇总:HAVING suppNum>400

结果排序:ORDER BY custNum desc

取前N条:LIMIT 10

SELECT

   COUNT(s.name) suppNum,

   COUNT(c.name) custNum

ON

   nation WHERE nation>5

FROM

   Supplier s BY nationkey

   UNION

   Customer c BY nationkey

HAVING suppNum>400

ORDER BY custNum DESC

LIMIT 10

后记

正确创建了DQL元数据文件,把它部署到DQL服务器上,然后以JDBC的方式给外部提供查询服务,通常会由一些WEB业务系统使用。

下一篇文章就实践WEB系统中如何使用DQL查询,更进一步的,把DQL查询模型可视化到WEB页面上,由WEB用户选择所需信息,自动生成DQL语句后,从DQL服务器上查询出数据。

DQL查询模型更符合人们对现实事务的自然思维,因此DQL可视化查询,具有较好的易用性、灵活性。