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,其它表设置为1MB;B列为表名;C列为字段名,#开头的字段是主键维字段;
把这8个表的信息写入A10的序表中;
11、12、13行逐个创建组表,把文本数据写入组表文件。
二、 创建DQL元数据文件
创建虚表
打开DQL设计器,新建元数据文件:
添加表,选择上面生成的组表customer.ctx文件,看到字段、主键将自动识别出来:
用同样的方法把剩余的表都加载进来,然后元数据文件保存为TPCH.glmd:
在customer、nation、part、region、supplier这几个表设置“Load into memory”,DQL要求维表要预先加载入内存(虚表本身并不要求):
设置DQL表
引入虚表
切换到DQL标签下,这时DQL下还没有任何表:
点击菜单Tool -> Generate table from pseudo table
选出刚才加载的所有虚表:
DQL表创建成功,自动识别出了主键、数据类型:
对表名、字段名稍作调整,表名首字母改为大写,字段名去掉“C_”等前缀:
创建逻辑维表:年、月、日期
查询数据时,按照年、月、日期分组很常见,所以需要对这些维要预定义出来,在工具栏中点击添加逻辑表的按钮,表名设置为Year,再添加字段,字段名也用Year,设置为主键,数据类型选择整数类型:
同样步骤添加月维表,月维的字段值包含年份信息,也是整数类型,比如202308,表示2023年8月:
其它表中的日期字段大多是日期类型,所以日期就不用类似20230815这样的整数类型了,设置成日期类型:
设置表间关联关系
选择Lineitem表,切换到外键标签页,添加外键,然后设置每个外键的关联关系。如fk2外键,用Lineitem的PARTKEY字段关联Part维表的主键PARTKEY字段:
所有表设置好外键关联后,切换到View标签页,可以看到中间位置列出所有分类维,DQL表列两边,每个表通过连线连接它涉及的所有分类维:
和常规ER图一样,都能表达各表的关联关系,但DQL通过引入分类维概念,形成这种总线形式的关系图。
Supplier、Customer表通过外键关联到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(?),其中?代表当前的日期维值,用SPL的month(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,查询出订单的客户的国家的地区的名称,涉及到的Orders、Customer、Nation、Region四个表会自动关联:
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可视化查询,具有较好的易用性、灵活性。
英文版