1.1 使用Flume收集數據落地HDFS
1.1.1 實現方案
log4j和flume整合
配置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就是把MR(MapReduce)封裝了下,可以使用類似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假死
執行其他hql(select * from tb_user)順利執行;但只要執行需要mr的hql(select * from tb_user)就假死不動,查看日志如紅框異常。什么原因呢?
Hive是運行在Hadoop集群上的,集群的計算框架配置為了yarn,所以hdfs和yarn都處於運行中才可以。執行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,要看到4個hadoop的進程
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
兩個數據庫default和jtdb
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去處理這些數據。比如flume,flume收集的信息已經落在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.txt、jp.txt、en.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;
需要保證hive為latin1格式
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 問題:Hive和Hbase的區別?
Hive是基於Hadoop的一個數據倉庫工具。可以將結構化的數據文件映射為一張數據庫表,並提供完整的sql查詢功能,可以將sql語句轉換為MapReduce任務進行運行。
Hbase是非結構化數據庫,專門處理非結構化數據。
Hive是高吞吐量,一次可以處理大量數據,但是連接時還是不夠快,不是一個低延遲的結果,無法直接做到快速響應,秒級甚至毫秒級響應。Hive是一次寫入多次讀取,而數據庫要支持CRUD增刪改查操作,所以Hive無法直接做數據庫。
1.5.3 問題:數據庫和數據倉庫的區別?
Hive是基於Hadoop的數據倉庫。那什么是數據庫倉庫呢?和我們學習的mysql、oracle等數據庫有什么區別呢?
數據倉庫與數據庫的主要區別在於:
數據庫是面向事務的設計,數據倉庫是面向主題設計的
數據庫一般存儲在線實時數據,數據倉庫存儲的一般是歷史數據
數據庫設計是盡量避免冗余,數據倉庫在設計是有意引入冗余
數據庫是為捕獲數據而設計,數據倉庫是為分析數據而設計
1.5.4 問題:為什么Hive不支持行級的插入、更新、刪除?
因為Hive是基於Hadoop的,Hadoop底層不支持數據的行級插入、更新、刪除。那Hadoop為何不支持呢?
Hadoop底層HDFS是分布式的文件存儲。1.0默認以64M來分塊,2.0默認以128M來分塊。如果在中間插入內容勢必影響這個文件的這個位置之后的所有分塊,而且HDFS是存儲海量數據的,可能僅僅因為插入1字節,但導致后面的所有分塊都要重新分配,工作量巨大,耗時長。一只螞蟻卻引來了大廈的垮塌。得不償失,所以Hadoop選擇了拒絕,選擇了不支持。