上海墨智科技笔试题

一、hive抽样,分区和分桶区别?

1.分区

Hive分区是指按照数据表的某列或某些列分为多个区,区从形式上可以理解为文件夹,比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多。那其实这个情况下,我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。

2.分桶

对于每一个表或者是分区,Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive是针对某一列进行分桶。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶中。分桶的好处是可以获得更高的查询处理效率。使取样更高效。

3.抽样

在大规模数据量的数据分析及建模任务中,往往针对全量数据进行挖掘分析时会十分耗时和占用集群资源,因此一般情况下只需要抽取一小部分数据进行分析及建模操作。Hive提供了数据取样(SAMPLING)的功能,能够根据一定的规则进行数据抽样,目前支持数据块抽样,分桶抽样和随机抽样,具体如下所示:

  1. 数据块抽样(tablesample()函数) 
    1) tablesample(n percent) 根据hive表数据的大小按比例抽取数据,并保存到新的hive表中。如:抽取原hive表中10%的数据 
    (注意:测试过程中发现,select语句不能带where条件且不支持子查询,可通过新建中间表或使用随机抽样解决) 
    create table xxx_new as select * from xxx tablesample(10 percent) 
    2)tablesample(n M) 指定抽样数据的大小,单位为M。 
    3)tablesample(n rows) 指定抽样数据的行数,其中n代表每个map任务均取n行数据,map数量可通过hive表的简单查询语句确认(关键词:number of mappers: x)
  2. 分桶抽样 
    关于Hive中的分桶表(Bucket Table),在以后的文章中将会介绍,其实就是根据某一个字段Hash取模,放入指定数据的桶中,比如将表lxw1234按照ID分成100个桶,其算法是hash(id) % 100,这样,hash(id) % 100 = 0的数据被放到第一个桶中,hash(id) % 100 = 1的记录被放到第二个桶中。分桶表在创建时候使用CLUSTER BY语句创建。

Hive中分桶表取样的语法是:

table_sample: TABLESAMPLE(BUCKET x OUT OF y [ON colname])

其中x是要抽样的桶编号,桶编号从1开始,colname表示抽样的列,y表示桶的数量。

例子1:

SELECT COUNT(1)

FROM lxw1 TABLESAMPLE(BUCKET 1 OUT OF 10 ON rand());

该语句表示将表lxw1随机分成10个桶,抽样第一个桶的数据;

前面介绍过,表lxw1总大小约为64816816,总记录数为:2750714

出来的结果基本上是原表的十分之一,注意:这个结果每次运行是不一样的,因为是按照随机数进行分桶取样的。

例子2

如果基于一个已经分桶表进行取样,将会更有效率。

执行下面的语句,创建一个分桶表,并插入数据:

CREATE TABLE lxw1_bucketed(pcid STRING)

CLUSTERED BY(pcid) INTO 10BUCKETS;

INSERT overwrite TABLElxw1_bucketed

SELECT pcid FROM lxw1;

表lxw1_bucketed按照pcid字段分成10个桶,下面的语句表示从10个桶中抽样第一个桶的数据:

SELECT COUNT(1) FROMlxw1_bucketed TABLESAMPLE(BUCKET 1 OUT OF 10 ON pcid);

很好理解。

再看这个:

SELECT COUNT(1) FROMlxw1_bucketed TABLESAMPLE(BUCKET 1 OUT OF 20 ON pcid)

表只有10个桶,如果指定20,看结果:

结果差不多是源表记录的1/20,Hive在运行时候,会在第一个桶中抽样一半的数据。

还有一点:

如果从源表中直接分桶抽样,也能达到一样的效果,比如:

SELECT COUNT(1) FROM lxw1TABLESAMPLE(BUCKET 1 OUT OF 20 ON pcid);

区别在于基于已经分桶的表抽样,查询只会扫描相应桶中的数据,而基于未分桶表的抽样,查询时候需要扫描整表数据,先分桶,再抽样。

3.随机抽样(rand()函数) 

1)使用rand()函数进行随机抽样,limit关键字限制抽样返回的数据,其中rand函数前的distribute和sort关键字可以保证数据在mapper和reducer阶段是随机分布的,案例如下: 
select * from table_name where col=xxx distribute by rand() sort by rand()limit num; 
2)使用order关键词 
案例如下: 
select * from table_name where col=xxx order by rand() limit num; 
经测试对比,千万级数据中进行随机抽样 order by方式耗时更长,大约多30秒左右。


二、groupbykey和reducebykey的区别?

reduceByKey用于对每个key对应的多个value进行merge操作,最重要的是它能够在本地先进行merge操作,并且merge操作可以通过函数自定义。

groupByKey也是对每个key进行操作,但只生成一个sequence。需要特别注意“Note”中的话,它告诉我们:如果需要对sequence进行aggregation操作(注意,groupByKey本身不能自定义操作函数),那么,选择reduceByKey/aggregateByKey更好。这是因为groupByKey不能自定义函数,我们需要先用groupByKey生成RDD,然后才能对此RDD通过map进行自定义函数操作。

上面得到的wordCountsWithReduce和wordCountsWithGroup是完全一样的,但是,它们的内部运算过程是不同的。

三、map和flatmap的区别?

1.map(func)

将原数据的每个元素传给函数func进行格式化,返回一个新的分布式数据集。(原文:Return a newdistributed dataset formed by passing each element of the source through afunction func.)

2.flatMap(func)

map(func)类似,但是每个输入项和成为0个或多个输出项(所以func函数应该返回的是一个序列化的数据而不是单个数据项)(原文:Similar tomap, but each input item can be mapped to 0 or more output items (so funcshould return a Seq rather than a single item).)

区别对比:

map(func)函数会对每一条输入进行指定的func操作,然后为每一条输入返回一个对象;而flatMap(func)也会对每一条输入进行执行的func操作,然后每一条输入返回一个相对,但是最后会将所有的对象再合成为一个对象;从返回的结果的数量上来讲,map返回的数据对象的个数和原来的输入数据是相同的,而flatMap返回的个数则是不同的。

通过上图可以看出,flatMap其实比map多的就是flatten操作。

示例比较:


四、map和foreach的区别?

Map和foreach都是对rdd中的每一个元素进行操作的。

foreach 对 RDD 中的每个元素都应用 f 函数操作,不返回 RDD 和 Array, 而是返回Uint;foreach 算子通过用户自定义函数对每个数据项进行操作。

map将原数据的每个元素传给函数func进行格式化,返回一个新的分布式数据集。

五、如果一个数据文件有100亿行,怎样做时间优化?

使用mapPartition 算子,增加并行度。


六、使用Linux命令读取文本文件中的某一列数据?

使用awk命令获取文本的某一行,某一列

1、打印文件的第一列() awk '{print $1}' filename
2
、打印文件的前两列() awk '{print $1,$2}' filename
3
、打印完第一列,然后打印第二列  awk '{print $1 $2}' filename
4
、打印文本文件的总行数 awk 'END{print NR}' filename
5
、打印文本第一行awk 'NR==1{print}' filename
6
、打印文本第二行第一列sed -n "2, 1p" filename | awk '{print $1}'
    shell
里面的赋值方法有两种,格式为
    1) arg=`(
命令)`
    2) arg=$(
命令)
因此,如果想要把某一文件的总行数赋值给变量nlines,可以表达为:
    1) nlines=`(awk 'END{print NR}' filename)`
或者
    2) nlines=$(awk 'END{print NR}' filename)

七、使用Linux命令修改文本文件中的指定数据?

sed 可以直接修改文件的内容,不必使用管道命令或数据流重导向!不过,由於这个动作会直接修改到原始的文件,所以请你千万不要随便拿系统配置来测试! 

替换文本中的字符串:(将book替换为books)

s 替换指定字符

sed  's/book/books/'  filename

/g 标记会替换每一行中的所有匹配:

sed   's/book/books/g'   filename

八、如果一个rdd有300个分区,如何将它变成3000个?

思路:重分区

1.coalesce

defcoalesce(numPartitions: Int, shuffle: Boolean = false)(implicit ord:Ordering[T] = null): RDD[T]

该函数用于将RDD进行重分区,使用HashPartitioner

第一个参数为重分区的数目,第二个为是否进行shuffle,默认为false;

以下面的例子来看:

1.    scala>var data = sc.textFile("/tmp/lxw1234/1.txt")
2.   data: org.apache.spark.rdd.RDD[String]=MapPartitionsRDD[53] at textFile at :21
3.    
4.   scala> data.collect
5.   res37:Array[String]=Array(hello world, hello spark, hello hive, hi spark)
6.    
7.   scala> data.partitions.size
8.   res38:Int=2  //RDD data默认有两个分区
9.    
10.  scala>var rdd1 = data.coalesce(1)
11.  rdd1: org.apache.spark.rdd.RDD[String]=CoalescedRDD[2] at coalesce at :23
12.   
13.  scala> rdd1.partitions.size
14.  res1:Int=1   //rdd1的分区数为1
15.   
16.  scala>var rdd1 = data.coalesce(4)
17.  rdd1: org.apache.spark.rdd.RDD[String]=CoalescedRDD[3] at coalesce at :23
18.   
19.  scala> rdd1.partitions.size
20.  res2:Int=2   //如果重分区的数目大于原来的分区数,那么必须指定shuffle参数为true,否则,分区数不变。
21.   
22.  scala>var rdd1 = data.coalesce(4,true)
23.  rdd1: org.apache.spark.rdd.RDD[String]=MapPartitionsRDD[7] at coalesce at :23
24.   
25.  scala> rdd1.partitions.size
26.  res3:Int=4

2.repartition

defrepartition(numPartitions: Int)(implicit ord: Ordering[T] = null): RDD[T]

该函数其实就是coalesce函数第二个参数为true的实现

1.    scala>var rdd2 = data.repartition(1)
2.   rdd2: org.apache.spark.rdd.RDD[String]=MapPartitionsRDD[11] at repartition at :23
3.    
4.   scala> rdd2.partitions.size
5.   res4:Int=1
6.    
7.   scala>var rdd2 = data.repartition(4)
8.   rdd2: org.apache.spark.rdd.RDD[String]=MapPartitionsRDD[15] at repartition at :23
9.    
10.  scala> rdd2.partitions.size
11.  res5:Int=4


猜你喜欢

转载自blog.csdn.net/big_data1/article/details/80874385
今日推荐