【数仓】数仓DWS层搭建(续)及索引
本次主要是干DWS层的另外两个宽表,商品主题日统计宽表和用户主题日统计宽表。因为是销售商品给用户,而且销售主题日统计宽表在上次已经干完了,这另外两个宽表基本换汤不换药。还有MySQL的索引之类的一些东西,让我认识到SQL也是有性能(效率)的评级的,网上可以搜到MySQL的评级分类,以后基本将自己的SQL优化到const这种效率的SQL就很牛了。
Hive相关配置参数
1 | --分区 |
变量命名规则
建表语法需要在Hive中写, 因为Presto不支持.
给变量起名主要有四
种规范,大多数语言都支持前两种, 后两种, 部分语言支持, 部分语言不支持.
- 规范1: 大驼峰命名法, 也叫 双峰驼命名法, 即: 每个单词的首字母都大写, 其它小写.
例如: HelloWorld, MaxValue- 规范2: 小驼峰命名法, 也叫 单峰驼命名法, 即: 从第二个单词开始, 每个单词的首字母都大写, 其它小写.
例如: helloWorld, maxValue, zhangSanAge- 规范3: 蛇形命名法, 单词间用下划线隔开.
例如: max_value, min_value, hello_world, zhang_san_age- 规范4: 串行命名法, 单词间用中划线隔开.
例如: max-value, min-value, zhang-san-age好用的起名网站,参考: https://unbug.github.io/codelf/
DWS之商品主题日统计宽表
主题需求
指标
1
2
3下单次数、下单件数、下单金额、被支付次数、被支付件数、被支付金额、被退款次数、被退款件数、被退款金额、被加入购物车次数、被加入购物车件数、被收藏次数、好评数、中评数、差评数
--总共15个指标维度
1
日期(day)+商品
本主题建表操作
注意:建表操作需要在hive中执行,presto不支持hive的建表语法。
Step1建表
在DWS层创建dws_sku_daycount
1 | create table yp_dws.dws_sku_daycount |
分析字段
分析我们要的数据来源于哪些表的哪些字段
说白了就是一个一个字段的对,DWS层的数据基本是来源于DWB层的,但是也是有可能来源一DWD层,虽然这样做会导致血缘关系混乱,但是做这的一切都是利于分析。
指标:
下单次数、下单件数、下单金额、被支付次数、被支付件数、被支付金额、被退款次数、被退款件数、被退款金额、被加入购物车次数、被加入购物车件数、被收藏次数、好评数、中评数、差评数维度:
日期 + 商品(id, 名字)
分析结论
根据建表的字段,我们可以分析出
下单次数、下单件数、下单金额为一组,
被支付次数、被支付件数、被支付金额为一组,
被退款次数、被退款件数、被退款金额为一组等等…..
这里我们发现前三组的字段中都有相同的字段,可以放到一个order_base表中
dt, order_id, goods_id, goods_name
buy_num(购买商品的数量), total_price
1 | 组1: 下单次数、下单件数、下单金额 |
Step2下单支付退款等指标
准备数据源
准备数据源,用于计算: 下单次数、下单件数、下单金额、 被支付次数、被支付件数、被支付金额、 被退款次数、被退款件数、被退款金额
这里是写链式CTE表达式,先写 order_base,因为我们发现前三组的字段中都有相同的字段,所以我们可以把这些相同的字段放到一个order_base表中。
1 | with order_base as ( |
下单-次数-件数-金额
1 | order_count as ( |
被支付-次数-件数-金额
1 | payment_count as ( |
被退款次数、件数、金额
1 | refund_count as ( |
Step3购物车收藏等指标
被加入购物车次数、件数
1 | cart_count as ( |
被收藏次数
1 | favor_count as ( |
Step4好中差评相关指标
1 | evaluation_count as ( |
Step5完整实现
对上述的6个结果做合并, 即: 合并 order_count, payment_count, refund_count, cart_count, favor_count, evaluation_count
最终发现一个Bug,重复的数据会有三行
union all和 full outer join的区别。
1 | insert into hive.yp_dws.dws_sku_daycount |
这里union all合并之后,通过dt,sku_id分组,通过max(string),sum(int)函数的原因是将数据进行合并。
如果直接使用full outer join就不用分组然后再累加了。
这里需要说明一下假设有stu表
id name money 1 null 0 2 张三 100
1
2 select max(name) from stu; -- 最终结果为张三,因为根据哈希值进行比较的
select sum(money) from stu; -- 最终结果为100,因为另一条数据值为null
另一种写法:
1 | ----注意,如果session无法选中presto数据源---------- |
模板
1 | with order_base as ( |
DWS之用户主题日统计宽表
建表:
1 | create table yp_dws.dws_user_daycount |
最终实现:
1 | insert into yp_dws.dws_user_daycount |
索引
索引是什么
在数据库中,索引指的是提供指向存储在表的指定列中的数据值的指针(地址),数据库使用索引以找到特定值,然后顺指针找到包含该值的行。
- 索引的优点
大大提高查询的效率
- 索引的缺点
降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。MySQL支持自动更新索引。
- 建立索引会
占用磁盘空间
的索引文件。
索引使用的注意事项
- 当创建索引之后,根据具有索引的字段查询,效率才能体现。
MySQL索引
MySQL的索引分类
普通索引
普通索引是最基本的索引,它没有任何限制。
1
2
3
4
5
6
7
8
9
10
11
12
13CREATE INDEX indexName ON table_name (column_name);
--也可以在建表的时候同时指定索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER NOT NULL ,
`content` text CHARACTER NULL ,
`time` int(10) NULL DEFAULT NULL ,
PRIMARY KEY (`id`),
INDEX index_name (title(length))
)
--length为可选参数,表示索引的长度,只有字符串类型的字段才能指定索引长度唯一索引
与普通索引类似,不同的就是:==索引列的值必须唯一==,但允许有空值。
1
2
3
4
5
6
7
8
9
10CREATE UNIQUE INDEX indexName ON table(column(length));
--建表的时候创建索引
CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) CHARACTER NOT NULL ,
`content` text CHARACTER NULL ,
`time` int(10) NULL DEFAULT NULL ,
UNIQUE indexName (title(length))
);主键索引
一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。
一般是在建表的时候同时创建主键索引。
1
2
3
4
5CREATE TABLE `table` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`title` char(255) NOT NULL ,
PRIMARY KEY (`id`)
);组合索引
指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。
使用组合索引时==遵循最左前缀==集合。
1 | ALTER TABLE mytable ADD INDEX name_city_age (name(10),city,age); |
Hive索引
Hive 0.7版本之后,开始支持索引,但是功能很弱。
Hive3.0版本之后,直接移除了索引
Hive中如何使用索引:
- 使用物化视图 自动更新
- 使用ORC、Parquet等格式文件。这些文件格式本身列式存储,内部特性支持查询效率的提高。
ORC之行组索引
Row Group Index
Row Group Index行组索引
ORC为每个stripe建立的包含min/max值的索引,就称为Row Group Index,也叫min-max Index,或者Storage Index。
1
2
3
4
51、在建立ORC格式表时,指定表参数’orc.create.index’=’true’之后,便会建立Row Group Index;
2、需要注意的是,为了使Row Group Index有效利用,向表中加载数据时,必须对需要使用索引的字段进行排序,否则,min/max会失去意义。
3、另外,这种索引通常用于数值型字段的查询过滤优化上。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17--CTAS
CREATE TABLE t_text_2 stored AS ORC
TBLPROPERTIES
('orc.compress'='SNAPPY',
'orc.create.index'='true', --开启行组索引
'orc.stripe.size'='10485760',
'orc.row.index.stride'='10000') --索引条目之间的行数(必须> = 1000)
AS
SELECT xxxx
FROM t_text_1
DISTRIBUTE BY id sort BY id;
--参数hive.optimize.index.filte 表示是否自动使用索引,默认为false(不使用);
--如果不设置该参数为true,那么ORC的索引当然也不会使用。
--执行sql之前,为了使用索引,应该设置下面的参数
set hive.optimize.index.filter=true;
ORC之Bloom Filter过滤器
Bloom Filter Index
hive中布隆过滤器索引
在建表时候,通过表参数==orc.bloom.filter.columns=”pcid”==来指定为那些字段建立BloomFilter索引;
这样,在生成数据的时候,会在每个stripe中,为该字段建立BloomFilter的数据结构;
当查询条件中包含==对该字段的=号过滤时候,先从BloomFilter中获取以下是否包含该值==,如果不包含,则跳过该stripe。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18CREATE TABLE t_text_2 stored AS ORC
TBLPROPERTIES
('orc.compress'='SNAPPY',
'orc.create.index'='true',
"orc.bloom.filter.columns"="pcid", --布隆过滤器 对pcid进行索引
'orc.stripe.size'='10485760',
'orc.row.index.stride'='10000')
AS
SELECT xxxx
FROM t_text_1
DISTRIBUTE BY id sort BY id;
--执行查询
SET hive.optimize.index.filter=true;
SELECT COUNT(1) FROM t_text_2 WHERE id >= 0 AND id <= 1000
AND pcid IN ('0005E26F0DCCDB56F9041C','A');