大資料4.1 - Flume整合案例+Hive資料倉

項羽齊發表於2018-04-08

1.1 使用Flume收集資料落地HDFS

1.1.1 實現方案

 

  log4jflume整合

配置log4j.properties

log4j.rootLogger = info,stdout,flume

log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %m%n

# appender flume
log4j.appender.flume = org.apache.flume.clients.log4jappender.Log4jAppender
log4j.appender.flume.Hostname = hadoop01
log4j.appender.flume.Port = 22222
log4j.appender.flume.UnsafeMode = true

 

  配置flume-jt.properties

#命名Agent a1的元件
a1.sources  =  r1
a1.sinks  =  k1
a1.channels  =  c1

#描述/配置Source
a1.sources.r1.type  =  avro
a1.sources.r1.bind  =  hadoop01
a1.sources.r1.port  =  22222

#描述Sink
a1.sinks.k1.type  =  hdfs
a1.sinks.k1.hdfs.path = hdfs://hadoop01:9000/jt/data

#描述記憶體Channel
a1.channels.c1.type  =  memory
a1.channels.c1.capacity  =  1000 
a1.channels.c1.transactionCapacity  =  100

#為Channle繫結Source和Sink
a1.sources.r1.channels  =  c1
a1.sinks.k1.channel  =  c1

 

  複製依賴jar檔案

進入共享目錄

cd /usr/local/src/hadoop/hadoop-2.7.1/share/hadoop/common

     

複製檔案

cp *.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

 

cd /usr/local/src/hadoop/hadoop-2.7.1/share/hadoop/common/lib

cp commons-configuration-1.6.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

cp hadoop-auth-2.7.1.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

cp htrace-core-3.1.0-incubating.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

cp commons-io-2.4.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

 

cd /usr/local/src/hadoop/hadoop-2.7.1/share/hadoop/hdfs

cp hadoop-hdfs-2.7.1.jar /usr/local/src/flume/apache-flume-1.6.0-bin/lib

否則啟動和執行時會報錯:

java.lang.NoClassDefFoundError: org/apache/hadoop/io/SequenceFile$CompressionType

java.io.IOException: No FileSystem for scheme: hdfs

  啟動Agent

[root@localhost conf]# ../bin/flume-ng agent -c ./ -f ./flume-jt.properties -n a1 -Dflume.root.logger=INFO,console &

#注意在conf配置檔案目錄下執行

  訪問資料

啟動專案

 

 

訪問埋點頁面

 

在控制檯列印資料

 

1.1.7 以及flume會寫資料到HDFS

 

1.1.8 檢視下資料

 

注意:這不是亂碼,是資料編碼採用了GBK,資料本身沒問題。

1.2 Apache Hive 

1.2.1 概述

1.2.1.1 Hadoop分散式計算的缺點

    開發除錯繁瑣,週期長。客戶需要立即出結果,可開發MR非常耗時,難寫

    需要對Hadoop底層工作原理及api熟悉,才能開發出比較高質量的分散式程式

    用java語言開發,其它語言支援不夠友好

1.2.1.2 概述

 

Hive起源於Facebook,它是建立在 Hadoop 上的資料倉儲基礎構架。它提供了一系列的工具,可以用來進行資料提取轉化載入(ETL),這是一種可以儲存、查詢和分析儲存在 Hadoop 中的大規模資料的機制。Hive 定義了簡單的類 SQL 查詢語言,稱為 HQL,它允許熟悉 SQL 的使用者查詢資料。同時,這個語言也允許熟悉 MapReduce 開發者的開發自定義的 mapper reducer 來處理內建的 mapper reducer 無法完成的複雜的分析工作。

 

 

1.2.1.3 基本概念

    Hive 中所有的資料都儲存在 HDFS 中,Hive 中包含以下資料模型:(Table),外部表(External Table),分割槽(Partition),桶(Bucket)

    Hive 中的 Table 和資料庫中的 Table 在概念上是類似的,每一個 Table Hive 中都有一個相應的目錄儲存資料。

    artition 對應於資料庫中的 Partition 列的密集索引,但是 Hive Partition 的組織方式和資料庫中的很不相同。在 Hive 中,表中的一個 Partition 對應於表下的一個目錄,所有的 Partition 的資料都儲存在對應的目錄中。

    Buckets 對指定列計算 hash,根據 hash 值切分資料,目的是為了並行,每一個 Bucket 對應一個檔案。

    External Table 指向已經在 HDFS 中存在的資料,可以建立 Partition。它和 Table 在後設資料的組織上是相同的,而實際資料的儲存則有較大的差異。

1.2.1.4 應用場景

Hive 構建在基於靜態批處理的Hadoop 之上,Hadoop 通常都有較高的延遲並且在作業提交和排程的時候需要大量的開銷。例如,Hive 在幾百MB 的資料集上執行查詢一般有分鐘級的時間延遲。因此,Hive 並不適合那些需要低延遲的應用,例如,聯機事務處理(OLTP)。

Hive 查詢操作過程嚴格遵守Hadoop MapReduce 的作業執行模型,Hive 將使用者的HiveQL 語句通過直譯器轉換為MapReduce 作業提交到Hadoop 叢集上,Hadoop 監控作業執行過程,然後返回作業執行結果給使用者。Hive 的最佳使用場合是大資料集的批處理作業,例如,網路日誌分析。

Hive 在載入資料過程中不會對資料進行任何的修改,只是將資料移動到HDFS Hive 設定的目錄下,因此,Hive 不支援對資料的改寫和新增,所有的資料都是在載入的時候確定的。

1.2.1.5 特點

    支援索引,加快資料查詢。

    不同的儲存型別,例如,純文字檔案、HBase中的檔案。

    將後設資料儲存在關聯式資料庫中,大大減少了在查詢過程中執行語義檢查的時間。

    可以直接使用儲存在Hadoop 檔案系統中的資料。

    內建大量使用者函式UDF 來操作時間、字串和其他的資料探勘工具,支援使用者擴充套件UDF 函式來完成內建函式無法實現的操作。

    類SQL 的查詢方式,將SQL 查詢轉換為MapReduce job Hadoop叢集上執行。

    不支援線上事務處理,也不支援行級的插入、更新和刪除。

1.2.2 安裝配置

1.2.2.1 Hadoop叢集規劃

Hive是在Hadoop的基礎上,所以先需要安裝Hadoop叢集。

主機名

IP

安裝的軟體

程式

hadoop01

192.168.163.129

jdk、hadoop

namenode resourcemanager

hadoop02

192.168.163.130

jdk、hadoop

datanode secondnamenode

hadoop03

192.168.163.131

jdk、hadoop

datanode

1.2.2.2 Hive安裝配置

cd /usr/local/src

mkdir hive #建立目錄

cd hive #進入目錄

apache-hive-1.2.0-bin.tar.gz #上傳,注意和Hadoop的版本對應

tar -xvf apache-hive-1.2.0-bin.tar.gz #解壓,基於jdk

cd apache-hive-1.2.0-bin/bin/ #進入目錄

 

1.1.1.1 啟動Hadoop叢集

cd /usr/local/src/hadoop/hadoop-2.7.1/sbin #進入hadoop目錄

./stop-dfs.sh #停止之前的HDFS服務

start-all.sh #啟動hadoop服務

jps  #啟動4個服務NameNode,DataNode,SecondaryNameNode,ResourceManager

1.1.1.2 執行Hive

./hive #啟動hive,必須有jdk+Hadoop

 

1.2.3 基礎操作

1.2.3.1 常見命令

hive> show databases; #檢視資料庫,預設只有default

hive> use default; #開啟預設資料庫

hive> create table tb_teacher(id int,name string); #建立表

hive> exit; #退出hive

 

hive> create database jtdb; #建立庫

hive> use jtdb; #開啟庫

 

hive> create table tb_user(id int, name string); #建立表

hive> show tables; #檢視所有表

hive> desc tb_user; #檢視錶結構

hive> show create table tb_user; #檢視建立表語句

OK

執行結果:

CREATE TABLE `tb_user`(

  `id` int,

  `name` string)

ROW FORMAT SERDE

  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'

STORED AS INPUTFORMAT

  'org.apache.hadoop.mapred.TextInputFormat'

OUTPUTFORMAT

  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

LOCATION

  'hdfs://192.168.163.129:9000/user/hive/warehouse/jtdb.db/tb_user'

TBLPROPERTIES (

  'transient_lastDdlTime'='1511504310')

Time taken: 0.362 seconds, Fetched: 13 row(s)

1.2.3.2 檢視資料庫

 

可以看到jtdb.db是一個目錄,tb_user表也是個目錄。

1.2.3.3 插入資料

插入單條

insert into tb_user values(1, ‘tony’); 

1.2.3.4 批量載入資料

資料檔案user.txt

1 嚴嵩

2 徐階

3 高供

4 張居正

批量插入資料

load data local inpath '/usr/local/src/user.txt' into table tb_user;

執行結果

Loading data to table jtdb.tb_user

Table jtdb.tb_user stats: [numFiles=1, totalSize=38]

OK

Time taken: 0.744 seconds

hive> select * from tb_user;

OK

NULL NULL

NULL NULL

NULL NULL

NULL NULL

神奇怎麼都是NULL呢?如果說沒有插入那怎麼會顯示的剛好4條呢?

先看看資料

 

可以看出,其實表下面的資料就是上傳的檔案。

Hive中要指定txt檔案中列的分隔符:

create table tb_user2 (id bigint, name string) row format delimited fields terminated by ' ';

load data local inpath '/usr/local/src/user.txt' into table tb_user2;

1.2.3.5 給同一個表再次載入資料

編輯user2.txt,修改資料為拼音,然後載入

load data local inpath '/usr/local/src/user3.txt' into table tb_user2;

select * from tb_user2;

查詢資料發現都在

hive> select * from tb_user2;

OK

1 嚴嵩

2 徐階

3 高供

4 張居正

Time taken: 0.338 seconds, Fetched: 8 row(s)

 

1.2.3.6 小結

 

l hive中的資料庫對應hdfs/user/hive/warehouse目錄下以.db結尾的目錄

l hive中的表對應hdfs/user/hive/warehouse/[db目錄]中的一個目錄

l hive中的資料對應當前hive表對應的hdfs目錄中的檔案

l 執行select count(*) from tb_user; 可以看出hive會將命令轉換為mapreduce執行

l 行級別的增刪改是不允許的

 

可以看到Hive就是把MRMapReduce)封裝了下,可以使用類似SQL語句的形式來操作Hadoop,直接使用HDFS

1.2.4 常見問題

1.2.4.1 檢視日誌

有錯誤時hive不在console控制檯顯示,這時就需要檢視日誌。

hive/conf/ hive-log4j.properties 檔案中記錄了Hive日誌的儲存情況,

預設的儲存情況:

hive.root.logger=WARN,DRFA

hive.log.dir=/tmp/${user.name} # 預設的儲存位置

hive.log.file=hive.log  # 預設的檔名

Job日誌又儲存在什麼地方呢 ?

//Location of Hive run time structured log file

HIVEHISTORYFILELOC("hive.querylog.location", "/tmp/" + System.getProperty("user.name")),

預設儲存與 /tmp/{user.name}目錄下。

檢視日誌

cd /tmp/root

tail –f hive.log

1.2.4.2 Hive假死

 

執行其他hqlselect * from tb_user)順利執行;但只要執行需要mrhqlselect * from tb_user)就假死不動,檢視日誌如紅框異常。什麼原因呢?

Hive是執行在Hadoop叢集上的,叢集的計算框架配置為了yarn,所以hdfsyarn都處於執行中才可以。執行jps必須看到ResourceManager才可以。沒有就單獨啟動其服務。

因為我們分散式叢集配置在hadoop03上啟動資源管理服務,所以在hadoop03啟動

 

一路回車,yes,密碼root,最終jps看到ResourceManager。再執行select count(*) from tb_user,雖然還是比較慢,但可以順利執行完畢。

1.2.4.3 Hive啟動報錯$HADOOP_HOME

Cannot find hadoop installation: $HADOOP_HOME or $HADOOP_PREFIX must be set or hadoop must be in the path

解決辦法:

指定HADOOP_HOME路徑

cd /usr/local/src/hive/apache-hive-1.2.0-bin/conf

cp hive-env.sh.template hive-env.sh

增加HADOOP_HOME

 

HADOOP_HOME=/usr/local/src/hadoop/hadoop-2.7.1

1.2.4.4 Hive啟動報錯Safe mode

 

Hadoop在啟動時有個安全模式,其在啟動時有些工作要做,後設資料的處理,DataNode的等待等過程。需要一段時間,遇到時需要等一段時間,耐心稍微等一會。過會自動就會好。

如果長時間還報錯還在安全模式可以手工設定退出安全模式

 [root@hadoop01 bin]# pwd

/usr/local/src/hadoop/hadoop-2.7.1/bin

[root@hadoop01 bin]# ./hadoop dfsadmin -safemode leave

DEPRECATED: Use of this script to execute hdfs command is deprecated.

Instead use the hdfs command for it.

 

Safe mode is OFF

[root@hadoop01 bin]#

引數value的說明如下:

l enter - 進入安全模式

l leave - 強制NameNode離開安全模式

l get - 返回安全模式是否開啟的資訊

l wait - 等待,一直到安全模式結束

1.2.5 Derby資料庫後設資料丟失問題及解決辦法

1.2.5.1 ApacheDerby的問題

./hive show databases;操作正常,bin/hive 查詢會發現之前的表沒有了,為什麼呢?

hive會把這些資訊存放在傳統的關係型資料庫中。如果不指定它會存放在預設的資料庫,它是傳統file檔案型別資料庫derby。它有個缺點,只認當前目錄中的metastore_db。所以執行不在hive/bin目錄中時,就無法讀取到metastrom_db檔案,從而之前的庫和表都不見了。

 

所以要注意,換了路徑後會新產生metastore_db,從而資訊丟失。這是derby資料庫的問題。幸好hive還支援另一種關係型資料庫mysql

1.2.5.2 安裝MySQL

cd /usr/local/src #進入目錄

mkdir mysql #建立目錄

cd mysql #進入目錄

上傳檔案到目錄中

MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm

MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm

 

rpm -qa |grep -i mysql #查詢是否有mysql

#查詢mysql系統中已經有舊的mysql版本:mysql-libs-5.1.71-1.el6.x86_64

rpm -ev --nodeps mysql-libs-5.1.71-1.el6.x86_64 #刪除舊的版本

groupadd mysql #增加使用者組

useradd –r –g mysql mysql #增加使用者mysql,加入使用者組

chown -R mysql:mysql /usr/local/mysql/data #設定資料存放目錄的寫許可權

rpm -ivh MySQL-server-5.6.29-1.linux_glibc2.5.x86_64.rpm #服務端

rpm -ivh MySQL-client-5.6.29-1.linux_glibc2.5.x86_64.rpm #客戶端

1.2.5.3 初次配置MySQL重設密碼

cd /etc/init.d #進入到mysql執行目錄

#預設mysql不允許遠端訪問,所以要以安全模式啟動,允許遠端訪問

mysqld_safe --user=mysql --skip-grant-tables --skip-networking &

執行結果:

[1] 4469

[root@hadoop01 init.d]# 171220 18:23:27 mysqld_safe Logging to '/var/lib/mysql/hadoop01.err'.

171220 18:23:27 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql

修改密碼:

mysql -u root mysql #root賬號登入,訪問mysql資料庫

#修改root賬號的密碼

mysql> update user set password=PASSWORD('root') where user='root';

mysql> flush privileges; #更新許可權

mysql> quit #退出

service mysql stop #關閉安全模式的服務

service mysql start #啟動正常的服務

mysql -u root –proot #連線進入mysql

ps -ef|grep mysql #檢視mysql的安裝執行路徑

1.2.5.4 檢視mysql資訊

mysql> \s

--------------

mysql  Ver 14.14 Distrib 5.6.29, for Linux (x86_64) using  EditLine wrapper

 

Connection id: 6

Current database:

Current user: root@localhost

SSL: Not in use

Current pager: stdout

Using outfile: ''

Using delimiter: ;

Server version: 5.6.29 MySQL Community Server (GPL)

Protocol version: 10

Connection: Localhost via UNIX socket

Server characterset: latin1

Db     characterset: latin1

Client characterset: utf8

Conn.  characterset: utf8

UNIX socket: /var/lib/mysql/mysql.sock

Uptime: 2 hours 16 min 52 sec

 

Threads: 2  Questions: 42  Slow queries: 0  Opens: 67  Flush tables: 1  Open tables: 60  Queries per second avg: 0.005

1.2.5.5 修改後設資料儲存到MySQL

cd /usr/local/src/hive/apache-hive-1.2.0-bin/conf

cp hive-default.xml.template hive-site.xml #複製模板檔案改名

模板中3000多行都是預設值,既然預設值都可以刪除,只留下資料庫配置

hive-site.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>

  <property>

    <name>javax.jdo.option.ConnectionURL</name>

    <value>jdbc:mysql://hadoop01:3306/hive?createDatabaseIfNotExist=true</value>

  </property>

  <property>

    <name>javax.jdo.option.ConnectionDriverName</name>

    <value>com.mysql.jdbc.Driver</value>

  </property>

  <property>

    <name>javax.jdo.option.ConnectionUserName</name>

    <value>root</value>

  </property>

  <property>

    <name>javax.jdo.option.ConnectionPassword</name>

    <value>root</value>

  </property>

</configuration>

此時如果啟動hive會報兩個錯誤:

1、 找不到資料庫驅動jar

2、 資料庫預設不允許訪問,必須開放遠端訪問許可權

上傳mysql驅動包到指定目錄

/usr/local/src/hive/apache-hive-1.2.0-bin/lib

mysql-connector-java-5.1.32.jar

 

mysql –uroot –proot

#授權開啟遠端訪問

grant all privileges on *.* to 'root'@'%' identified by 'root' with grant option;

注意:如果上面語句出錯,提示必須先set password,那執行下面語句

set password = PASSWORD('root');

flush privileges; #更新許可權

如果上面修改後還提示許可權錯誤,修改指定機器

grant all privileges on *.* to 'root'@'hadoop01' identified by 'root' with grant option;

flush privileges; #更新許可權

1.2.5.6 建立資料

cd /usr/local/src/hive/apache-hive-1.2.0-bin/bin #進入hive目錄

hive> create database jtdb; #建立jtdb資料庫

hive> use jtdb; #開啟資料庫

hive> create table tb_user(id int,name string); #建立tb_user

1.2.5.7 Derby的問題得到解決

cd /usr/local/src/hive/apache-hive-1.2.0-bin/bin #進入目錄

/.hive #當前目錄下執行

cd /usr/local/src/hive/apache-hive-1.2.0-bin #進入目錄

bin/hive #其他目錄執行

hive> show databases;

執行結果:

OK

default

jtdb

Time taken: 0.828 seconds, Fetched: 2 row(s)

可以看到解決了Derby資料庫後設資料的丟失問題。

1.2.6 常見問題

1.2.6.1 密碼過期問題

報錯:

ERROR 1862 (HY000): Your password has expired. To log in you must change it using a client that supports expired passwords.

解決辦法:

use mysql

select * from mysql.user where user='root' \G

update user set password_expired='N' where user='root';

flush privileges;

quit;

1.2.6.2 Connection refused

報錯:

Hive出現Caused by: java.net.ConnectException: Connection refused

解決辦法:

檢視程式jps,要看到4hadoop的程式

jps  #啟動4個服務NameNode,DataNode,SecondaryNameNode,ResourceManager

1.2.6.3 Hadoop namenode無法啟動

執行start-all.sh的時候發現JPS一下namenode沒有啟動,每次開機都得重新格式化一下namenode才可以。其實問題就出在tmp檔案,預設的tmp檔案每次重新開機會被清空,與此同時namenode的格式化資訊就會丟失,於是我們得重新配置一個tmp檔案目錄。首先在home目錄下建立一個hadoop_tmp目錄

sudo mkdir /usr/local/src/hadoop/hadoop-2.7.1/hadoop_tmp

然後修改hadoop/conf目錄裡面的core-site.xml檔案,加入以下節點:

<property>

<name>hadoop.tmp.dir</name>

    <value>/usr/local/src/hadoop/hadoop-2.7.1/hadoop_tmp</value>

</property>

重新格式化Namenode

cd /usr/local/src/hadoop/hadoop-2.7.1/bin

hadoop namenode -format

然後啟動hadoop

cd  /usr/local/src/hadoop/hadoop-2.7.1/sbin

start-all.sh

執行下jps命令就可以看到NameNode了。

1.2.7 後設資料庫

1.2.7.1 啟動hive後檢視mysql資料庫

 

 

1.2.7.2 資料庫DBS

兩個資料庫defaultjtdb

 

1.2.7.3 TBLS

資料庫表

 

有個很關鍵的欄位TBL_TYPE表的型別叫MANAGED_TABLE,叫“內部表”

1.2.7.4 COLUMNS_V2

資料庫表的欄位

 

1.2.7.5 儲存位置SDS

記錄表所在的位置。CD_ID表的編號,LOCATION HDFS中的位置

 

1.3 外部

1.3.1 外部表概念

內部表MANAGED_TABLE,它是先有的表,後有的資料。但實際工作中,往往我們是先有資料,然後利用hive去處理這些資料。比如flumeflume收集的資訊已經落在HDFS上了。某天我們突然想分析這些資料了。這樣的情況下就先有了資料,後要建立表。那這些表就叫外部表。

那外部表怎麼產生呢?

先上傳檔案到HDFS

1.3.2 HDFS新增資料檔案

/usr/local/src/book.txt,注意資料以tab為分隔符

1 三國演義

2 水滸傳

3 西遊記

4 紅樓夢

執行命令很慢,執行時稍等片刻

cd /usr/local/src/hadoop/hadoop-2.7.1 #進入hadoop命令

bin/hdfs dfs -mkdir /data #建立data

bin/hdfs dfs -put /usr/local/src/book.txt /data #上傳到data目錄

bin/hdfs dfs -ls /data #列目錄

1.3.3 建立外部表

hive> create external table ext_book(id int, name string) row format delimited fields terminated by '\t' location '/data';

檢視TBLS,可以看到我們剛建立的外部表

 

檢視SDS,表的儲存位置,就是我們配置的/data

 

1.3.4 查詢外部表資料

hive> select * from ext_book;

OK

1 三國演義

2 水滸傳

3 西遊記

4 紅樓夢

可以看到,所謂外部表就是HDFS某個目錄下的檔案內容,就是我們剛剛上傳的book.txt的內容。

1.3.5 內部表和外部表的差異

當刪除內部表時,內部表後設資料和資料都會被刪除

當刪除外部表時,外部表後設資料會被刪除,資料還存在

刪除內部表:

hive> show tables;

OK

ext_book

tb_user

Time taken: 0.164 seconds, Fetched: 2 row(s)

hive> drop table tb_user;

OK

Time taken: 1.155 seconds

hive> show tables;

OK

ext_book

Time taken: 0.145 seconds, Fetched: 1 row(s)

hive>

檢視內部表,列表中已經被刪除

http://192.168.163.129:50070/explorer.html#/user/hive/warehouse/jtdb.db

刪除外部表:

hive> show tables;

OK

ext_book

Time taken: 0.137 seconds, Fetched: 1 row(s)

hive> drop table ext_book;

OK

Time taken: 0.406 seconds

hive> show tables;

OK

Time taken: 0.132 seconds

hive>

檢視外部表,列表中的檔案還存在

http://192.168.163.129:50070/explorer.html#/data

1.4 分割槽

1.4.1 分割槽表概念

Hive中最重的作用就是建立資料倉儲,以不同維度來建立資料集合,本質以空間換時間。而資料庫倉庫就和分割槽表緊密相連。這也是Hive區別與其他產品的優勢。

對資料進行分割槽可以提高查詢效率。

1.4.1.1 建立單分割槽表

1.4.1.1.1 建立分割槽表

hive> create table tb_book(id int,name string) partitioned by (category string) row format delimited fields terminated by '\t';

可見,就是增加了一句partitioned by (category string)

1.4.1.1.2 準備資料

zh.txt

1 西遊記

2 紅樓夢

3 三國演義

4 水滸傳

jp.txt

1 一休

2 聖鬥士

3 灌籃高手

4 犬夜叉

en.txt

1 Pride and Prejudice (傲慢與偏見)

2 Sense and Sensibility (理智與情感)

3 The Great Gatsby(了不起的蓋茨比)

上傳檔案到/usr/local/src目錄中

1.4.1.1.3 插入資料

hive> load data local inpath '/usr/local/src/zh.txt' overwrite into table tb_book partition (category='china');

hive> load data local inpath '/usr/local/src/jp.txt' overwrite into table tb_book partition (category='jp');

hive> load data local inpath '/usr/local/src/en.txt' overwrite into table tb_book partition (category='en');

注:insert into並不是hive中標準的用法,而應該用load

1.4.1.1.4 存放結構

 

可以看到分割槽表就多了級目錄而已,上傳的檔案就被放在了對應的目錄下,但就因為多了級目錄意義就非常重大。我們先繼續來看後面總結時再說它的意義。

1.4.1.1.5 查詢資料

hive> select * from tb_book;

OK

1 西遊記 china

2 紅樓夢 china

3 三國演義 china

4 水滸傳 china

1 Pride and Prejudice (傲慢與偏見) en

2 Sense and Sensibility (理智與情感) en

3 The Great Gatsby(了不起的蓋茨比) en

1 一休 jp

2 聖鬥士 jp

3 灌籃高手 jp

4 犬夜叉 jp

Time taken: 0.31 seconds, Fetched: 11 row(s)

可以看到我們的表是兩列,在最後又按分類加了一列。

如果整表查詢,和以前沒什麼差別,效能一樣。但是如何下面的差就不一樣了。

Time taken: 0.31 seconds, Fetched: 11 row(s)

hive> select * from tb_book where category='china';

OK

1 西遊記 china

2 紅樓夢 china

3 三國演義 china

4 水滸傳 china

Time taken: 0.655 seconds, Fetched: 4 row(s)

hive>

大家思考下,這樣查詢有什麼不同?

如果不分割槽,所有內容zh.txtjp.txten.txt的內容都在一起,而category只是表的一列屬性。如果要查china就要所有資料都遍歷一遍,要一條一條判斷,從中過濾出要的內容。那我們現在做了分割槽,我們查詢條件很特殊,我們是按分割槽的條件進行查詢。那有什麼不同。還用遍歷那麼多資料嗎?還要做判斷嗎?是不直接返回。哪個查詢效率高,是不一目瞭然。分割槽後查詢效率高。

回顧下我們說過的資料庫倉庫,把資料按不同的維度事先處理,那將來查詢時效率是不就高了。按什麼維度呢?category,預先處理把資料分到不同分割槽。

多分割槽

1.4.1.2 常見錯誤

For direct MetaStore DB connections, we don’t support retries at the client level.

 

現象:

hive中插入資料時提示失敗,但是在瀏覽器中檢視時發現資料上傳成功了。但在hive中查詢表中的資料時,沒有顯示。

解決辦法:

這是由於字符集的問題,需要配置MySQL的字符集:

Mysql> alter database hive character set latin1;

需要保證hivelatin1格式

 

1.4.1.3 建立多分割槽表

1.4.1.3.1 建立分割槽表

hive> create table tb_book2(id int, name string) partitioned by(category string,gender string) row format delimited fields terminated by '\t';

hive> desc tb_book2;

OK

id                   int                                      

name                 string                                   

category             string                                   

gender               string                                   

   

# Partition Information    

# col_name             data_type            comment             

   

category             string                                   

gender               string                                   

Time taken: 0.252 seconds, Fetched: 10 row(s)

hive> show create table tb_book2;

OK

CREATE TABLE `tb_book2`(

  `id` int,

  `name` string)

PARTITIONED BY (

  `category` string,

  `gender` string)

ROW FORMAT DELIMITED

  FIELDS TERMINATED BY '\t'

STORED AS INPUTFORMAT

  'org.apache.hadoop.mapred.TextInputFormat'

OUTPUTFORMAT

  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'

LOCATION

  'hdfs://192.168.163.129:9000/user/hive/warehouse/jtdb.db/tb_book2'

TBLPROPERTIES (

  'transient_lastDdlTime'='1514343503')

Time taken: 0.172 seconds, Fetched: 16 row(s)

hive>

1.4.1.3.2 準備資料

將資料先進行分維度,也就是分成多個檔案,然後再逐個匯入。

zh-male.txt

1 西遊記 吳承恩 男 1296

2 紅樓夢 曹雪芹 男 1510

3 三國演義 羅貫中 男 1330

4 水滸傳 施耐庵 男 1715

jp-male.txt

1 一休 大川久男 男 1975

2 聖鬥士 車田正美 男 1974

3 灌籃高手 井上雄彥 男 1996

jp-fmale.txt 

4 犬夜叉 高橋留美子 女 1996

en-male.txt

3 The Great Gatsby(了不起的蓋茨比) 菲茨傑拉德 男 1919

en-fmale.txt

1 Pride and Prejudice (傲慢與偏見) ·奧斯汀 女 1813

2 Sense and Sensibility (理智與情感) ·奧斯汀 女 1775

上傳檔案到/usr/local/src目錄中

1.4.1.3.3 插入資料

hive> load data local inpath '/usr/local/src/zh-male.txt' overwrite into table tb_book2 partition(category='china',gender='male');

 

hive> load data local inpath '/usr/local/src/jp-male.txt' overwrite into table tb_book2 partition(category='jp',gender='male');

hive> load data local inpath '/usr/local/src/jp-fmale.txt' overwrite into table tb_book2 partition(category='jp',gender='fmale');

 

hive> load data local inpath '/usr/local/src/en-male.txt' overwrite into table tb_book2 partition(category='en',gender='male');

hive> load data local inpath '/usr/local/src/en-fmale.txt' overwrite into table tb_book2 partition(category='en',gender='fmale');

注:insert into並不是hive中標準的用法,而應該用load

1.4.1.3.4 存放結構

 

 

  

可以看到多維分割槽表就多了幾級目錄而已,上傳的檔案就被放在了對應的目錄下。

檢視SDS

 

1.4.1.3.5 查詢資料

查詢所有資料

hive> select * from tb_book2;

OK

1 西遊記 china male

2 紅樓夢 china male

3 三國演義 china male

4 水滸傳 china male

1 Pride and Prejudice (傲慢與偏見) en fmale

2 Sense and Sensibility (理智與情感) en fmale

3 The Great Gatsby(了不起的蓋茨比) en male

4 犬夜叉 jp fmale

1 一休 jp male

2 聖鬥士 jp male

3 灌籃高手 jp male

Time taken: 0.261 seconds, Fetched: 11 row(s)

查詢部分資料

hive> select * from tb_book2 where category='en' and gender='fmale';

OK

1 Pride and Prejudice (傲慢與偏見) en fmale

2 Sense and Sensibility (理智與情感) en fmale

Time taken: 0.267 seconds, Fetched: 2 row(s)

hive>

1.4.1.4 總結

這麼做的意義何在呢?例如我只查英文的女作家的where category='en' and gender='fmale'。這樣就只查en目錄下的fmale目錄。少差近1/4的資料。那查詢速度就飛速提升。

1.5 Hive的誤區

1.5.1 問題:Hive能做資料庫嗎?

Hive雖然用起來感覺像是資料庫,但實際不是。為什麼呢?我們知道資料庫能完成CRUD操作,但Hive是基於Hadoop的,Hadoop是隻能新增和追加的不能刪除和修改的。Hive是無法做到實時的CRUD操作的。另外它還需要轉換成MR執行,那它的效能不可能特別高。它的本質是一種離線大資料分析工具。

1.5.2 問題:HiveHbase的區別?

Hive是基於Hadoop的一個資料倉儲工具。可以將結構化的資料檔案對映為一張資料庫表,並提供完整的sql查詢功能,可以將sql語句轉換為MapReduce任務進行執行。

Hbase是非結構化資料庫,專門處理非結構化資料。

Hive是高吞吐量,一次可以處理大量資料,但是連線時還是不夠快,不是一個低延遲的結果,無法直接做到快速響應,秒級甚至毫秒級響應。Hive是一次寫入多次讀取,而資料庫要支援CRUD增刪改查操作,所以Hive無法直接做資料庫。

1.5.3 問題:資料庫和資料倉儲的區別?

Hive是基於Hadoop的資料倉儲。那什麼是資料庫倉庫呢?和我們學習的mysqloracle等資料庫有什麼區別呢?

 

資料倉儲與資料庫的主要區別在於:

  資料庫是面向事務的設計,資料倉儲是面向主題設計的

  資料庫一般儲存線上實時資料,資料倉儲儲存的一般是歷史資料

  資料庫設計是儘量避免冗餘,資料倉儲在設計是有意引入冗餘

  資料庫是為捕獲資料而設計,資料倉儲是為分析資料而設計

1.5.4 問題:為什麼Hive不支援行級的插入、更新、刪除?

因為Hive是基於Hadoop的,Hadoop底層不支援資料的行級插入、更新、刪除。那Hadoop為何不支援呢?

Hadoop底層HDFS是分散式的檔案儲存。1.0預設以64M來分塊,2.0預設以128M來分塊。如果在中間插入內容勢必影響這個檔案的這個位置之後的所有分塊,而且HDFS是儲存海量資料的,可能僅僅因為插入1位元組,但導致後面的所有分塊都要重新分配,工作量巨大,耗時長。一隻螞蟻卻引來了大廈的垮塌。得不償失,所以Hadoop選擇了拒絕,選擇了不支援。

相關文章