任务描述
本关任务:计算每个股票每天的总交易量。
相关知识
为了完成本关任务,你需要掌握:1.随机抽样 2.桶表抽样 3.数据块抽样
随机抽样
使用RAND()
函数和LIMIT
关键字来获取样例数据,使用DISTRIBUTE
和SORT
关键字来保证数据是随机分散到mapper
和reducer
的。ORDER BY RAND()
语句可以获得同样的效果,但是性能没这么高。
/**从table表里随机抽取5行数据*/ //第一种: SELECT * FROM table DISTRIBUTE BY RAND() SORT BY RAND() LIMIT 2; //第二种(性能不太好): SELECT * FROM table ORDER BY RAND() LIMIT 2;
桶表抽样
① *Hive分桶*
对于每一个表(table
)或者分区, Hive
可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive
也是 针对某一列进行桶的组织。Hive
采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
桶(bucket
)是指将表或分区中指定列的值为key
进行hash
,hash
到指定的桶中,这样可以支持高效采样工作。
把表(或者分区)组织成桶(Bucket
)有两个理由:
获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
//创建一个分桶表(CLUSTERED BY 子句来指定划分桶所用的列和要划分的桶的个数) create table bucket_user ( id int, name string )clustered by(id) into 4 buckets row format delimited fields terminated by '\t' stored as textfile; //在这里,我们使用用户ID来确定如何划分桶(Hive使用对值进行哈希并将结果除 以桶的个数取余数)。
配置所需环境(必须):
要向分桶表中填充成员,需要将 hive.enforce.bucketing 属性设置为 true。①这 样,Hive 就知道用表定义中声明的数量来创建桶。然后使用 INSERT 命令即可。需要注意的是: clustered by和sorted by不会影响数据的导入,这意味着,用户必须自己负责数据如何如何导入,包括数据的分桶和排序 'set hive.enforce.bucketing = true' 可以自动控制上一轮reduce的数量从而适配bucket的个数,当然,用户也可以自主设置mapred.reduce.tasks去适配bucket个数,推荐使用'set hive.enforce.bucketing = true'
②桶表抽样
select * from table_name tablesample(bucket X out of Y on field); //X:从哪个桶开始抽取 Y:相隔几个桶后再次抽取 field:列名 注意:x的值必须小于等于y的值 //示例:bkt表(总共30个桶) select * from bkt tablesample(bucket 2 out of 6 on id) //表示从桶中抽取5(30/6)个bucket数据,从第2个bucket开始抽取,抽取的个数由每个桶中的数据量决定。相隔6个桶再次抽取,因此,依次抽取的桶为:2,8,14,20,26
数据块抽样
该方式允许 Hive
随机抽取N
行数据,数据总量的百分比(n
百分比)或N
字节的数据。
//抽取table表中50%的数据 SELECT * FROM table TABLESAMPLE (50 PERCENT); //抽取table表中30m的数据 SELECT * FROM table TABLESAMPLE (30M); //根据数据行数来取样 SELECT * FROM table TABLESAMPLE (200 ROWS); //这种方式可以根据行数来取样,但要特别注意:这里指定的行数,是在每个InputSplit中取样的行数,也就是,每个Map中都取样n ROWS。 如果有3个Map Task(InputSplit),每个取200行,总共600行
编程要求
根据提示,在右侧编辑器补充代码,计算每个股票每天的交易量。
- 采用桶表抽样的方法(从第二个桶开始抽样,每隔两个开始抽样);
- 创建分桶表
total_bucket
(以股票ID
进行分桶,共分为 6 个桶); - 数据从
total
表获取。
表名:total
col_name | data_type | comment |
tradedate |
string |
交易日期 |
tradetime |
string |
交易时间 |
securityid |
string |
股票ID |
bidpx1 |
string |
买入价 |
bidsize1 |
int |
买入量 |
offerpx1 |
string |
卖出价 |
bidsize2 |
int |
卖出量 |
部分数据如下所示:
20130724 145004 152896 2.62 6960 2.63 13000 20130724 145101 152896 2.86 13880 2.89 6270 20130724 145128 152896 2.85 327400 2.851 1500 20130724 145143 152896 2.603 44630 2.8 10650
数据说明:
(152896: 每种股票id) (20130724: 2013年7月24日) (145004: 14点50分04秒)
测试说明
平台会对你编写的代码进行测试:
预期输出:
交易日期 股票id
总交易量
20130722 125896 33823300 20130722 204001 24830700 20130722 412233 249769380 20130722 553211 742712700 20130722 745962 90592600 20130722 856947 161685600 20130723 204001 77617900 20130723 869547 258300900 20130724 152896 13158580 20130724 204001 48889500 20130724 745896 199706260 20130724 856974 14958220 20130724 881125 246118000 20130725 125896 1584560 20130725 425178 1286900 20130725 668452 1416400 20130725 745962 874720 20130725 789562 4073430 20130725 968956 508900 20130726 204001 263772500
----------禁止修改---------- create database if not exists mydb; use mydb; create table if not exists total( tradedate string, tradetime string, securityid string, bidpx1 string, bidsize1 int, offerpx1 string, bidsize2 int) row format delimited fields terminated by ',' stored as textfile; truncate table total; load data local inpath '/root/files' into table total; drop table if exists total_bucket; ----------禁止修改---------- ----------begin---------- ---------- 创建分桶 ---------- create table if not exists total_bucket ( tradedate string, securityid string, bidsize1 int, bidsize2 int )clustered by(securityid) into 6 buckets row format delimited fields terminated by ',' stored as textfile; set hive.enforce.bucketing = true; insert overwrite table total_bucket select tradedate, securityid, bidsize1, bidsize2 from total; select tradedate, securityid, sum(bidsize1 + bidsize2) from total_bucket tablesample(bucket 2 out of 2 on securityid) group by tradedate, securityid; ----------end----------