2023-02-16
數據 hive 開發
我們需要知道,所謂的“大數據”,指的是非常龐大的數據集。在一般的中型企業中,數據的規模往往能夠輕松的到達PB的規模,更不用提大型的企業了。這些數據中蘊藏著非常豐富的價值,而大數據開發人員需要使用各種工具,對這樣的數據集進行高效率的處理,從而挖掘出其中蘊藏的價值,讓其發光發熱。于是要解決的第一個問題就是數據存儲的問題。龐大的數據集,造成了在一臺機器上存儲不下的問題,此時就需要使用分布式的數據存儲方式,而HDFS就是來解決這樣的問題而存在的。
存儲的問題解決了,下面就是對這些數據進行計算、處理的問題了。我們需要對分布式文件系統上的數據文件進行計算,勢必會涉及到分布式計算的思想。但是如果在我們處理每一個需求的時候,都去從0開始開發一個分布式計算程序,會有很多的弊端。首先,對于開發人員來說,就是一個極大的學習成本,需要去了解到分布式計算的底層是如何實現的。其次,幾乎所有的分布式計算程序中,涉及到分布式計算的部分可以是共用的。因此只需要將這部分單獨的抽離出來即可,沒必要每一次做分布式計算程序的時候,都去關注底層的實現細節。于是就出現了MapReduce,解決了分布式計算的問題。
MapReduce的出現,確實在一定程度上簡化了開發人員的壓力,使得開發人員只需要將自己的工作重心放在業務邏輯的實現上面即可,不需要考慮到分布式計算的底層細節是如何實現的。但是,MapReduce的程序其實還是非常的麻煩的。想要去開發一個完整的MapReduce的程序,你必須設計至少3個類: Mapper、Reduer、Driver,而如果還需要處理更加復雜的數據的時候,可能還得設計分區器、自定義數據類型、Combiner、自定義分組等等類型,使得一個MR的程序非常的復雜。這還只是一個Job。如果你的業務邏輯比較復雜,此時可能還需要有多個Job串聯,又大大的增加了開發的難度。于是,在此基礎上,Hive誕生了!
Apache Hive是Apache旗下的頂級項目,是在大數據開發中非常非常熱門的組件,也是大數據開發必需要使用到的技術組件之一。什么是Hive呢?Hive是一個構建在Hadoop上的數據倉庫工具(框架),可以將結構化的數據文件映射成一張數據表,并可以使用類SQL的方式對這樣的數據文件進行讀、寫以及管理的操作。有很多人在提到Hive的時候,都會把Hive稱為是一個數據庫。但是Hive只是一個數據計算的工具,并不是一個數據庫!
而為什么一定要使用到Hive呢?其實使用Hive可以極大的簡化開發人員的開發成本,縮短項目周期。我們以一個案例為例,來對比一下MapReduce和Hive來處理同樣的需求的時候,有什么區別?
案例:
一個文件中記錄著手機流量的信息,記錄著手機號碼、MAC地址、訪問網址、上行流量、下行流量等信息。需要從這個文件中查詢出來每一個手機號碼的總上行、總下行、總流量信息。
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public class PhoneFlowReducer extends Reducer<text, text="" text,="" phoneflowbean,=""> {
@Override
protected void reduce(Text key, Iterablevalues, Context context) throws IOException, InterruptedException {
// 定義一個變量,用來統計總流量
int total = 0;
int total_up = 0;
int total_down = 0;
// 遍歷每一個手機號碼對應的一條流量信息
for (PhoneFlowBean value : values) {
total += value.getTotalFlow();
total_up += value.getUpFlow();
total_down += value.getDownFlow();
}
String res = String.format("%d\t%d\t%d", total_up, total_down, total);
context.write(key, new Text(res));
}
}
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public class PhoneFlowMapper extends Mapper<longwritable, text,="" phoneflowbean=""> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String[] props = value.toString().split("\t");
// 拆出手機號碼
String phoneNumber = props[1];
// 拆出上行流量
int upFlow = Integer.parseInt(props[8]);
// 拆出下行流量
int downFlow = Integer.parseInt(props[9]);
PhoneFlowBean bean = new PhoneFlowBean(phoneNumber, upFlow, downFlow);
context.write(new Text(phoneNumber), bean);
}
}
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public class PhoneFlowReducer extends Reducer<text, text="" text,="" phoneflowbean,=""> {
@Override
protected void reduce(Text key, Iterablevalues, Context context) throws IOException, InterruptedException {
// 定義一個變量,用來統計總流量
int total = 0;
int total_up = 0;
int total_down = 0;
// 遍歷每一個手機號碼對應的一條流量信息
for (PhoneFlowBean value : values) {
total += value.getTotalFlow();
total_up += value.getUpFlow();
total_down += value.getDownFlow();
}
String res = String.format("%d\t%d\t%d", total_up, total_down, total);
context.write(key, new Text(res));
}
}
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
/**
* @author 千鋒大數據教研院 - 章魚哥
* @company 北京千鋒互聯科技有限公司
*/
public class PhoneFlowDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
Configuration configuration = new Configuration();
configuration.set("mapreduce.framework.name", "local");
Job job = Job.getInstance(configuration);
job.setMapperClass(PhoneFlowMapper.class);
job.setReducerClass(PhoneFlowReducer.class);
job.setJarByClass(PhoneFlowDriver.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(PhoneFlowBean.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
FileInputFormat.setInputPaths(job, new Path("file/HTTP_20130313143750.dat"));
FileOutputFormat.setOutputPath(job, new Path("file/out2"));
System.exit(job.waitForCompletion(true) ? 0 : -1);
}
}
看到了吧,用MapReduce實現上述需求的時候,需要設計至少3個類:Mapper、Reducer、Driver,有些復雜的需求還需要自定義序列化類型,例如上述的PhoneFlowBean類。那么使用Hive如何解決這個需求呢?
# 建表
CREATE TABLE flow(
id string COMMENT 'this is id column',
phonenumber string,
mac string,
ip string,
url string,
urltype string,
uppacket int,
downpacket int,
upflow int,
downflow int,
issuccess int
)
COMMENT 'this is log table'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
stored as textfile;
# 查詢結果
select
phonenumber,
sum(upflow) total_up,
sum(downflow) total_down,
sum(upflow+downflow) total
from
flow
group by
phonenumber;
看到了吧,使用Hive來做同樣的需求,就是這么簡單!對HDFS上的結構化的數據文件進行表的映射,然后一條SQL就可以實現同樣的需求了!
因此,當我們需要處理到非常復雜的需求的時候,使用Hive來進行數據的處理將會變得非常的簡單,可以極大的減少開發人員的開發壓力,縮短開發人員的開發周期!
開班時間:2021-04-12(深圳)
開班盛況開班時間:2021-05-17(北京)
開班盛況開班時間:2021-03-22(杭州)
開班盛況開班時間:2021-04-26(北京)
開班盛況開班時間:2021-05-10(北京)
開班盛況開班時間:2021-02-22(北京)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2020-09-21(上海)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2019-07-22(北京)
開班盛況Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號