大数据组件测试题(节选)
单多选
1、Hive中外部表(EXTERNAL TABLE)的特性是? B
A. 删除表时会同时删除数据
B. 删除表时仅删除元数据
C. 必须与HBase表关联
D. 不支持分区
外部表数据存储在hdfs上某一目录中,删除表仅会删除元数据,而不会删除目录中的数据。
2、HBase的底层存储引擎基于哪种数据结构? B
A. B+树
B. LSM树
C. 红黑树
D. 哈希表
LSM树存储引擎和B树存储引擎一样,同样支持增、删、读、改、顺序扫描操作。而且通过批量存储技术规避磁盘随机写入问题。当然凡事有利有弊,LSM树和B+树相比,LSM树牺牲了部分读性能,用来大幅提高写性能。
LSM树原理把一棵大树拆分成N棵小树,它首先写入内存中,随着小树越来越大,内存中的小树会flush到磁盘中,磁盘中的树定期可以做merge操作,合并成一棵大树,以优化读性能。No-SQL数据库一般采用LSM树作为数据结构,HBase也不例外。
LSM和Btree差异就要在读性能和写性能进行取舍。在牺牲的同时,寻找其他方案来弥补。
1、LSM具有批量特性,存储延迟。当写读比例很大的时候(写比读多),LSM树相比于B树有更好的性能。因为随着insert操作,为了维护B树结构,节点分裂。读磁盘的随机读写概率会变大,性能会逐渐减弱。 多次单页随机写,变成一次多页随机写,复用了磁盘寻道时间,极大提升效率。
2、B树的写入过程:对B树的写入过程是一次原位写入的过程,主要分为两个部分,首先是查找到对应的块的位置,然后将新数据写入到刚才查找到的数据块中,然后再查找到块所对应的磁盘物理位置,将数据写入去。当然,在内存比较充足的时候,因为B树的一部分可以被缓存在内存中,所以查找块的过程有一定概率可以在内存内完成,不过为了表述清晰,我们就假定内存很小,只够存一个B树块大小的数据吧。可以看到,在上面的模式中,需要两次随机寻道(一次查找,一次原位写),才能够完成一次数据的写入,代价还是很高的。
3、LSM Tree放弃磁盘读性能来换取写的顺序性,似乎会认为读应该是大部分系统最应该保证的特性,所以用读换写似乎不是个好买卖。内存的速度远超磁盘,1000倍以上。而读取的性能提升,主要还是依靠内存命中率而非磁盘读的次数。
LSM数据更新只在内存中操作,没有磁盘访问,因此比B+树要快。对于数据读来说,如果读取的是最近访问过的数据,LSM树能减少磁盘访问,提高性能。 LSM树实质上就是在读写之间得取衡平,和B+树比相,它牲牺了部份读性能,用来大幅进步写性能。
3、Hive分区和分桶的区别是? A
A. 分区基于列值,分桶基于哈希
B. 分桶基于列值,分区基于哈希
C. 两者均基于列值
D. 两者均基于哈希
分区和分桶的区别
1、在HDFS上的效果区别,分区产生的是一个一个子文件夹,分桶产生的是一个一个文件
2、无论是分区还是分桶,在建表的时候都要指定字段,分区使用partitioned by指定分区字段,分桶使用clustered by指定分桶字段
3、partitioned by指定分区字段的时候,字段后面需要加上类型,而且不能在建表小括号中出现。clustered by指定分桶字段的时候,字段已经出现定义过了,只需要指定字段的名字即可
4、分区字段最好选择固定类别的,分桶字段最好选择值各不相同的。
5、分桶不是必须要建立在分区之上,可以不进行分区直接分桶
4、HDFS的哪些特性保证了数据可靠性?(多选) ACD
A. 副本机制
B. 心跳检测
C. 机架感知策略
D. 数据校验和数据
5、以下哪些是YARN ResourceManager的核心职责?(多选) ABD
A. 分配Container资源
B. 监控NodeManager状态
C. 执行MapReduce任务
D. 管理作业队列
6、Hive外部表(EXTERNAL TABLE)的特性包括?(多选) AD
A. 删除表时数据被保留
B. 必须指定LOCATION路径
C. 不支持分区
D. 元数据存储在MySQL中
7、关于Redis持久化机制,下列哪些描述是正确的?(多选) ACD
A. RDB持久化通过fork子进程生成数据快照,可能造成短暂服务停顿
B. AOF持久化默认每秒执行一次fsync,性能损耗可忽略不计
C. 同时开启RDB和AOF时,重启优先加载AOF文件恢复数据
D. 主从复制模式下,从节点默认禁用所有持久化机制
RDB和AOF到底该如何选择
不要仅仅使用RDB,因为那样会导致丢失很多数据。
也不要仅仅使用AOF,一是数据恢复慢,二是可靠性也不如RDB,毕竟RDB文件中存储的就是某一时刻实实在在的数据,而AOF只是操作指令,把数据转换为操作指令不一定是百分百没问题的。
综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择; 用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复。
8、DataX的核心特性包括哪些?(多选)ABD
A. 支持异构数据源之间的批式数据同步
B. 通过内存通道实现断点续传功能
C. 任务执行必须依赖Hadoop集群环境
D. 插件机制支持MySQL到Hive的字段类型自动映射
9、关于缓慢渐变维(SCD)处理,正确的方案是?(多选) ABC
A. 直接覆盖旧值,适合不关注历史变化的属性
B. 通过新增记录保留历史版本,需添加时间戳字段
C. 新增字段存储有限历史值,适合维度属性少量变更
D. 使用拉链表实现全量历史追踪,查询效率最高
10、以下哪些是解决Redis缓存穿透的有效方案?(多选) AB
A. 使用布隆过滤器预先过滤非法请求
B. 对空查询结果设置短时间缓存
C. 对热点数据设置互斥锁更新
D. 采用多级缓存架构(如Guava+Redis)
缓存击穿:对某个热点key的访问过多时,若这个key突然失效,则请求会大批涌入击穿缓存,直接访问数据库。
解决方案:为缓存数据设置不同的过期时间,避免数据同时失效,监控热点数据设置长生存时间。
引入二级缓存架构
针对热点数据进行预加载
缓存穿透:要查询的数据根本不存在
解决方案:对空值进行缓存,实时监控,使用布隆过滤器,接口校验。
缓存雪崩:原有缓存失效,新缓存未到时间,如:设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期。
解决方案:使用互斥锁只允许一条请求访问数据源,其他请求等待并共享结果。
将失效时间分散
使用多级架构
11、关于ClickHouse表引擎的描述,正确的有?(多选) ACD
A. MergeTree系列引擎支持数据分区(Partitioning)和主键索引
B. Log引擎适用于小数据量临时表,数据不持久化到磁盘
C. Kafka引擎可实现实时消费消息队列并自动维护偏移量
D. Memory引擎数据存储在内存中,服务重启后丢失
表引擎(表的类型)决定了:
- 数据如何存储,写入到哪里,以及从哪里读取。
- 支持哪些查询,以及如何支持。
- 并发数据访问。
- 索引的使用(如果存在的话)。
- 是否可以多线程请求执行。
- 数据复制参数
详细见官方文档:表引擎 | ClickHouse Docs
编程题
用户消费行为表(consumer_behavior.csv)
字段名数据类型格式要求业务说明user_id字符串U+6位数字(例:U000123)唯一用户标识order_time时间戳YYYY-MM-DD HH:MM:SS精确到秒的订单时间product_name字符串商品分类+型号商品全称(需考虑品类分布)original_price数值50-9999元(两位小数)商品吊牌价discount_price数值0-原价(两位小数)议价/促销优惠金额use_coupon布尔值0/1是否使用平台优惠券final_price计算字段原价-优惠价(两位小数)实际支付金额merchant_id字符串M+4位数字(例:M0042)外键关联商家表商家信息表(merchant_info.csv)
字段名数据类型生成规则示例merchant_id字符串M+4位数字M0042merchant_name字符串品牌+经营类型华为智能家居旗舰店1、数据导入
任务1:现在mysql中创建数据库,数据库名为 自己名字缩写_db。例如:xxx_db
任务2:在mysql中创建表consumer_behavior,merchant_info
任务3:编写java代码,将两张表数据插入对应表中
建表语句- -- consumer_behavior建表语句
- CREATE TABLE consumer_behavior(
- user_id VARCHAR(255) UNIQUE,
- order_time TIMESTAMP,
- product_name VARCHAR(255),
- original_price DECIMAL,
- discount_price DECIMAL,
- use_coupon BOOLEAN,
- final_price DECIMAL,
- merchant_id VARCHAR(255)
- );
- -- merchant_info建表语句
- CREATE TABLE merchant_info(
- merchant_id VARCHAR(255),
- merchant_name VARCHAR(255)
- );
复制代码 Java代码编写JDBC- // java代码编写
- //插入consumer_behavior
- package HomeWork;
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.math.BigDecimal;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.Timestamp;
- public class JDBCtest2 {
- public static void main(String[] args) {
- try {
- Connection conn = DriverManager.getConnection("jdbc:mysql://master:3306/ZRX_DB?useSSL=false", "root", "123456");
- BufferedReader br = new BufferedReader(new FileReader("src/HomeWork/data/consumer_behavior.csv"));
- PreparedStatement prep = conn.prepareStatement("insert into consumer_behavior (user_id,order_time,product_name,original_price,discount_price,use_coupon,final_price,merchant_id) values(?,?,?,?,?,?,?,?)");
- String line =null;
- br.readLine();
- while((line=br.readLine())!=null){
- String[] data = line.split(",");
- String user_id = data[0];
- String order_time = data[1];
- String product_name = data[2];
- String original_price = data[3];
- String discount_price = data[4];
- String use_coupon = data[5];
- String final_price = data[6];
- String merchant_id = data[7];
- prep.setString(1,user_id);
- prep.setTimestamp(2, Timestamp.valueOf(order_time));
- prep.setString(3,product_name);
- prep.setBigDecimal(4,new BigDecimal(original_price));
- prep.setBigDecimal(5,new BigDecimal(discount_price));
- prep.setInt(6, Integer.parseInt(use_coupon));
- prep.setBigDecimal(7,new BigDecimal(final_price));
- prep.setString(8,merchant_id);
- prep.addBatch();
- }
- br.close();
- prep.executeBatch();
- conn.close();
- System.out.println("数据已成功插入");
-
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
- //插入merchant_info
- package HomeWork;
- import java.io.BufferedReader;
- import java.io.FileReader;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- public class JDBCtest21 {
- public static void main(String[] args) {
- try {
- Connection conn = DriverManager.getConnection("jdbc:mysql://master:3306/ZRX_DB?useSSL=false", "root", "123456");
- BufferedReader br = new BufferedReader(new FileReader("src/HomeWork/data/merchant_info.csv"));
- PreparedStatement prep = conn.prepareStatement("insert into merchant_info (merchant_id,merchant_name) values (?,?)");
- String line =null;
- br.readLine();
- while ((line=br.readLine())!=null){
- String[] data = line.split(",");
- String merchant_id=data[0];
- String merchant_name=data[1];
- prep.setString(1,merchant_id);
- prep.setString(2,merchant_name);
- prep.addBatch();
- }
- br.close();
- prep.executeBatch();
- conn.close();
- System.out.println("数据已成功插入");
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- }
复制代码 2、数据同步
任务1:在hive中创建数据库,数据库名为 自己名字缩写大写_DB。例如:XXX_DB。(1分)
任务2:在数据库中创建两张外部表 ODS_CONSUMER_BEHAVIOR 和 ODS_MERCHANT_INFO。(1分)
任务3:编写datax数据同步任务,将这两张表数据同步到hive中。(4分)
建表语句- -- ods_consumer_behavior建表语句
- CREATE TABLE ods_consumer_behavior(
- user_id string,
- order_time timestamp,
- product_name string,
- original_price DECIMAL(8,2),
- discount_price DECIMAL(8,2),
- use_coupon int,
- final_price DECIMAL(8,2),
- merchant_id string
- )
- row format delimited fields terminated by ','
- location '/bigdataZrx33/data/input1';
- -- ods_merchant_info建表语句
- CREATE TABLE ods_merchant_info(
- merchant_id VARCHAR(255),
- merchant_name VARCHAR(255)
- )
- row format delimited fields terminated by ','
- location '/bigdataZrx33/data/input2';
复制代码 datax数据同步任务json编写
mysql2hive.json
mysql2hive2.json
- 表1:
- {
- "job": {
- "content": [
- {
- "reader": {
- "name": "mysqlreader",
- "parameter": {
- "column": [
- "user_id",
- "order_time",
- "product_name",
- "original_price",
- "discount_price",
- "use_coupon",
- "final_price",
- "merchant_id"
- ],
- "connection": [
- {
- "jdbcUrl": ["jdbc:mysql://192.168.255.100:3306/ZRX_DB?useUnicode=true&characterEncoding=utf-8&useSSL=false"],
- "table": ["consumer_behavior"]
- }
- ],
- "password": "123456",
- "username": "root"
- }
- },
- "writer": {
- "name": "hdfswriter",
- "parameter": {
- "column": [
- {
- "name":"user_id"
- "type":"string"
- },
- {
- "name":"order_time"
- "type":"timestamp"
- },
- {
- "name":"product_name"
- "type":"string"
- },
- {
- "name":"original_price"
- "type":"double"
- },
- {
- "name":"discount_price"
- "type":"double"
- },
- {
- "name":"use_coupon"
- "type":"boolean"
- },
- {
- "name":"final_price"
- "type":"double"
- },
- {
- "name":"merchant_id"
- "type":"string"
- }
- ],
- "defaultFS": "hdfs://master:9000",
- "fieldDelimiter": ",",
- "fileName": "input1",
- "fileType": "text",
- "path": "/bigdataZrx33/data/input1",
- "writeMode": "append"
- }
- }
- }
- ],
- "setting": {
- "speed": {
- "channel": "2"
- }
- }
- }
- }
- 表2:
- {
- "job": {
- "content": [
- {
- "reader": {
- "name": "mysqlreader",
- "parameter": {
- "column": [
- "merchant_id",
- "merchant_name"
- ],
- "connection": [
- {
- "jdbcUrl": ["jdbc:mysql://192.168.255.100:3306/ZRX_DB?useUnicode=true&characterEncoding=utf-8&useSSL=false"],
- "table": ["merchant_info"]
- }
- ],
- "password": "123456",
- "username": "root"
- }
- },
- "writer": {
- "name": "hdfswriter",
- "parameter": {
- "column": [
- {
- "name":"merchant_id"
- "type":"string"
- },
- {
- "name":"merchant_name"
- "type":"string"
- }
- ],
- "defaultFS": "hdfs://master:9000",
- "fieldDelimiter": ",",
- "fileName": "input2",
- "fileType": "text",
- "path": "/bigdataZrx33/data/input2",
- "writeMode": "append"
- }
- }
- }
- ],
- "setting": {
- "speed": {
- "channel": "2"
- }
- }
- }
- }
复制代码 3、数据清洗
任务:编写hive sql对用户的最终消费金额进行数据清洗, 并将结果导入到表DWD_CONSUMER_BEHAVIOR中
情况1:使用忧患券的
计算公式为:最终消费金额 = (商品原价 - 折扣价格)* 88%
情况2:未使用优惠券的
计算公式为:最终消费金额 = 商品原价 - 折扣价格
- -- 清洗后外部表建表语句 DWD_CONSUMER_BEHAVIOR
- CREATE TABLE dwd_consumer_behavior(
- user_id string,
- order_time timestamp,
- product_name string,
- original_price DECIMAL(8,2),
- discount_price DECIMAL(8,2),
- use_coupon int,
- final_price DECIMAL(8,2),
- merchant_id string,
- final_price_used_coupon DECIMAL(8,2)
- )
- row format delimited fields terminated by ','
- location '/bigdataZrx33/data/input3';
- -- 数据清洗sql
- insert into dwd_consumer_behavior
- select
- user_id,order_time,product_name,original_price,discount_price,use_coupon,final_price,merchant_id,
- case
- when use_coupon = 1 then (original_price-discount_price)*0.88
- when use_coupon = 0 then original_price-discount_price
- else 0
- end as final_price_used_coupon
- from ods_consumer_behavior;
复制代码 4、数据分析
- 需求1:使用hivesql查询分析出每个用户连续消费时间段的金额,连续开始日期,连续结束日期,天数,与下一次连续的间隔天数,将结果导入表DWS_CONSUMER_CONTINUE
- -- 外部表建表语句 DWS_CONSUMER_CONTINUE
- CREATE TABLE DWS_CONSUMER_CONTINUE (
- user_id STRING,
- start_date STRING,
- end_date STRING,
- total_amount DECIMAL(18, 2),
- days INT,
- next_days INT
- )
- row format delimited fields terminated by ','
- location '/bigdataZrx33/data/input4';
- -- sql
- INSERT into TABLE DWS_CONSUMER_CONTINUE
- SELECT
- user_id,
- start_date,
- end_date,
- total_amount,
- days,
- COALESCE(
- DATEDIFF(LEAD(start_date) OVER (PARTITION BY user_id ORDER BY start_date), end_date),
- 0
- ) AS next_days
- from(
- SELECT
- user_id,
- MIN(order_time) AS start_date,
- MAX(order_time) AS end_date,
- SUM(final_price_used_coupon) AS total_amount,
- COUNT(*) AS days
- FROM(
- SELECT
- user_id,
- order_time,
- final_price_used_coupon,
- DATE_SUB(order_time, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_time)) AS date_group
- FROM
- dwd_consumer_behavior
- )group_data GROUP BY user_id, date_group
- )continue_data;
复制代码
- 需求2:使用hivesql分析每个商家在每个月第一个星期7天内总消费金额,按照金额降序排序,将结果导入表DWS_MERCHANT_MONTH_FIRST_WEEK。
[code]-- 外部表建表语句 DWS_MERCHANT_MONTH_FIRST_WEEKcreate table DWS_MERCHANT_MONTH_FIRST_WEEK( merchant_id string, year_month string, total_price_first_week decimal(12,2))row format delimited fields terminated by ','location '/bigdataZrx33/data/input5';-- sqlINSERT into TABLE DWS_MERCHANT_MONTH_FIRST_WEEKSELECT merchant_id, DATE_FORMAT(order_time, 'yyyy-MM') AS year_month, SUM(final_price_used_coupon) AS total_price_first_weekFROM dwd_consumer_behaviorWHERE DAY(order_time) |