Hive(統計分析)
報錯1:Error: Error while compiling statement: FAILED: ParseException line 2:0 missing EOF at ‘select’ near ‘)’ (state=42000,code=40000)
解決辦法:把單引號換成雙引號
報錯2:0: jdbc:hive2://localhost:10000 (closed)>
解決辦法:start-all.sh (hdfs沒起來),或者mysql連線不上伺服器(連線本地(修改hive-site.xml檔案localhost換成本地IP地址)或者使用docker),netstat -ntlp | grep 3306,檢視3306端口占用情況。
1.內部連線:
select
a.name as aname,
a.num as anum,
b.name as bname,
b.nick as bnick
from t_a a
inner join t_b b
on a.name=b.name
2.注意:多個欄位必須用逗號隔開,一般語句不用逗號。
一、為什麼使用Hive
-
直接使用hadoop所面臨的問題 人員學習成本太高 專案週期要求太短 MapReduce實現複雜查詢邏輯開發難度太大
-
為什麼要使用Hive 操作介面採用類SQL語法,提供快速開發的能力。 避免了去寫MapReduce,減少開發人員的學習成本。 功能擴充套件很方便。、
二、Hive的特點
1.可擴充套件 Hive可以自由的擴充套件叢集的規模,一般情況下不需要重啟服務。
2.延展性 Hive支援使用者自定義函式,使用者可以根據自己的需求來實現自己的函式。
3.容錯 良好的容錯性,節點出現問題SQL仍可完成執行
三、hive安裝
1.最簡安裝:用內嵌derby作為元資料庫
準備工作:安裝hive的機器上應該有HADOOP環境(安裝目錄,HADOOP_HOME環境變數)
安裝:直接解壓一個hive安裝包即可
此時,安裝的這個hive例項使用其內嵌的derby資料庫作為記錄元資料的資料庫,此模式不便於讓團隊成員之間共享協作
2.標準安裝:將mysql作為元資料庫。
3.mysql安裝
1.上傳mysql安裝包
2.解壓:
[ [email protected] ~]# tar -xvf MySQL-5.6.26-1.linux_glibc2.5.x86_64.rpm-bundle.tar
3.安裝mysql的server包
[[email protected] ~]# rpm -ivh MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
依賴報錯:
缺perl
yum install perl
安裝完perl後 ,繼續重新安裝mysql-server
(可以配置一個本地yum源進行安裝:
1、先在vmware中給這臺虛擬機器連線一個光碟映象
2、掛在光碟機到一個指定目錄:mount -t iso9660 -o loop /dev/cdrom /mnt/cdrom
3、將yum的配置檔案中baseURL指向/mnt/cdrom
[[email protected] ~]# rpm -ivh MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
又出錯:包衝突conflict with
移除老版本的衝突包:mysql-libs-5.1.73-3.el6_5.x86_64
[[email protected] ~]# rpm -e mysql-libs-5.1.73-3.el6_5.x86_64 --nodeps
繼續重新安裝mysql-server
[[email protected] ~]# rpm -ivh MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
成功後,注意提示:裡面有初始密碼及如何改密碼的資訊
初始密碼:/root/.mysql_secret
改密碼指令碼:/usr/bin/mysql_secure_installation
4.安裝mysql的客戶端包:
[[email protected] ~]# rpm -ivh MySQL-client-5.6.26-1.linux_glibc2.5.x86_64.rpm
5.啟動mysql的服務端:
[[email protected] ~]# service mysql start
Starting MySQL. SUCCESS!
6.修改root的初始密碼:
[[email protected] ~]# /usr/bin/mysql_secure_installation 按提示
7.測試:
用mysql命令列客戶端登陸mysql伺服器看能否成功
[[email protected] ~]# mysql -uroot -proot
mysql> show databases;
8.給root使用者授予從任何機器上登陸mysql伺服器的許可權:
mysql> grant all privileges on *.* to 'root'@'%' identified by '你的密碼' with grant option;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
注意點:要讓mysql可以遠端登入訪問
最直接測試方法:從windows上用Navicat去連線,能連,則可以,不能連,則要去mysql的機器上用命令列客戶端進行授權:
在mysql的機器上,啟動命令列客戶端:
mysql -uroot -proot
mysql>grant all privileges on *.* to 'root'@'%' identified by 'root的密碼' with grant option;
mysql>flush privileges;
3.2.2.hive的元資料庫配置
vi conf/hive-site.xml
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
<description>password to use against metastore database</description>
</property>
</configuration>
2、上傳一個mysql的驅動jar包到hive的安裝目錄的lib中
3、配置HADOOP_HOME 和HIVE_HOME到系統環境變數中:/etc/profile
4、source /etc/profile
5、hive啟動測試
然後用命令啟動hive互動介面:
[[email protected] ~]# hive
4.hive使用方式
4.1.最基本使用方式
啟動一個hive互動shell
bin/hive
hive>
設定一些基本引數,讓hive使用起來更便捷,比如:
1、讓提示符顯示當前庫:
hive>set hive.cli.print.current.db=true;
2、顯示查詢結果時顯示欄位名稱:
hive>set hive.cli.print.header=true;
但是這樣設定只對當前會話有效,重啟hive會話後就失效,解決辦法:
在linux的當前使用者目錄中,編輯一個.hiverc檔案,將引數寫入其中:
vi .hiverc
set hive.cli.print.header=true;
set hive.cli.print.current.db=true;
4.2.啟動hive服務使用
啟動hive的服務:
[[email protected] hive-1.2.1]# bin/hiveserver2 -hiveconf hive.root.logger=DEBUG,console
上述啟動,會將這個服務啟動在前臺,如果要啟動在後臺,則命令如下:
nohup bin/hiveserver2 1>/dev/null 2>&1 &
啟動成功後,可以在別的節點上用beeline去連線
方式(1)
[[email protected] hive-1.2.1]# bin/beeline 回車,進入beeline的命令介面
輸入命令連線hiveserver2
beeline> !connect jdbc:hive2//mini1:10000
(hadoop01是hiveserver2所啟動的那臺主機名,埠預設是10000)
方式(2)
啟動時直接連線:
bin/beeline -u jdbc:hive2://mini1:10000 -n root
接下來就可以做正常sql查詢了
4.3.指令碼化執行
大量的hive查詢任務,如果用互動式shell來進行輸入的話,顯然效率及其低下,因此,生產中更多的是使用指令碼化執行機制:
該機制的核心點是:hive可以用一次性命令的方式來執行給定的hql語句
[[email protected] ~]# hive -e "insert into table t_dest select * from t_src;"
然後,進一步,可以將上述命令寫入shell指令碼中,以便於指令碼化執行 hive任務,並控制、排程眾多hive任務,示例如下:
vi t_order_etl.sh
#!/bin/bash
hive -e "select * from db_order.t_order"
hive -e "select * from default.t_user"
hql="create table default.t_bash as select * from db_order.t_order"
hive -e "$hql"
如果要執行的hql語句特別複雜,那麼,可以把hql語句寫入一個檔案:
vi x.hql
select * from db_order.t_order;
select count(1) from db_order.t_user;
然後,用hive -f /root/x.hql 來執行
5.hive建庫建表與資料匯入
5.1.建庫
hive中有一個預設的庫:
庫名: default
庫目錄:hdfs://hdp20-01:9000/user/hive/warehouse
新建庫:
create database db_order;
庫建好後,在hdfs中會生成一個庫目錄:
hdfs://hdp20-01:9000/user/hive/warehouse/db_order.db
5.2.建表
5.2.1.基本建表語句
use db_order;
create table t_order(id string,create_time string,amount float,uid string);
表建好後,會在所屬的庫目錄中生成一個表目錄
/user/hive/warehouse/db_order.db/t_order
只是,這樣建表的話,hive會認為表資料檔案中的欄位分隔符為 ^A
正確的建表語句為:
create table t_order(id string,create_time string,amount float,uid string)
row format delimited
fields terminated by ',';
這樣就指定了,我們的表資料檔案中的欄位分隔符為 ","
5.2.2.刪除表
drop table t_order;
刪除表的效果是:
hive會從元資料庫中清除關於這個表的資訊;
hive還會從hdfs中刪除這個表的表目錄;
5.2.3.內部表與外部表
內部表(MANAGED_TABLE):表目錄按照hive的規範來部署,位於hive的倉庫目錄/user/hive/warehouse中
外部表(EXTERNAL_TABLE):表目錄由建表使用者自己指定
create external table t_access(ip string,url string,access_time string)
row format delimited
fields terminated by ','location '/access/log';
匯入資料:在Linux下opt目錄建立一個數據檔案,然後用load data local inpath'路徑'into table 表名;
建立外部表:
create external table t_logdata(cid_sn string,os_ver string,resolution string,commit_time string,sdk_ver string,device_id_type string,device_model string,promotion_channel string,app_ver_name string,app_ver_code string,pid string,net_type string,device_id string,app_device_id string,release_channel string,country string,time_zone string,os_name string,manufacture string,commit_id string,app_token string,app_id string,language string,User_id string)
partitioned by(day string)
row format delimited
fields terminated by ','
location '/log-data-clean-data/';(HDFS的目錄)
向外部表分割槽匯入資料:
load data local(本地) inpath '/opt/log/data/*' into table t_logdata partition(day='2017-08-15');
load data inpath'/log-data-clean/android/*' into table t_logdata partition(day='2017-08-15');
select * from t_logdata where day='’2017-08-15';
外部表和內部表的特性差別:
1、內部表的目錄在hive的倉庫目錄中 VS 外部表的目錄由使用者指定
2、drop一個內部表時:hive會清除相關元資料,並刪除表資料目錄
3、drop一個外部表時:hive只會清除相關元資料;
一個hive的資料倉庫,最底層的表,一定是來自於外部系統,為了不影響外部系統的工作邏輯,在hive中可建external表來對映這些外部系統產生的資料目錄;
然後,後續的etl操作,產生的各種表建議用managed_table
5.2.4.分割槽表
分割槽表的實質是:在表目錄中為資料檔案建立分割槽子目錄,以便於在查詢時,MR程式可以針對分割槽子目錄中的資料進行處理,縮減讀取資料的範圍。
比如,網站每天產生的瀏覽記錄,瀏覽記錄應該建一個表來存放,但是,有時候,我們可能只需要對某一天的瀏覽記錄進行分析
這時,就可以將這個表建為分割槽表,每天的資料匯入其中的一個分割槽;
當然,每日的分割槽目錄,應該有一個目錄名(分割槽欄位)
一個分割槽欄位的例項:
示例如下:
1、建立帶分割槽的表
create table t_access(ip string,url string,access_time string)
partitioned by(dt string)
row format delimited
fields terminated by ',';
注意:分割槽欄位不能是表定義中的已存在欄位
show partitions t_logdata;
新增分割槽:
alter table t_logdata add partition (day='2017-08-16');
刪除分割槽:
alter table t_logdata drop partition (day='2017-08-15');
2、向分割槽中匯入資料
load data local inpath '/root/access.log.2017-08-04.log' into table t_access partition(dt='20170804');
load data local inpath '/root/access.log.2017-08-05.log' into table t_access partition(dt='20170805');
3、針對分割槽資料進行查詢
select count(*) as number from fengze where dt="20170806";(as後面加別名)
a、統計8月4號的總PV:
select count(*) from t_access where dt='20170804';
實質:就是將分割槽欄位當成表字段來用,就可以使用where子句指定分割槽了
b、統計表中所有資料總的PV:
select count(*) from t_access;
實質:不指定分割槽條件即可
多個分割槽欄位示例
建表:
create table t_partition(id int,name string,age int)
partitioned by(department string,sex string,howold int)
row format delimited fields terminated by ',';
導資料:
load data local inpath '/root/p1.dat' into table t_partition partition(department='xiangsheng',sex='male',howold=20);
5.2.5.CTAS建表語法
可以通過已存在表來建表:
1、create table t_user_2 like t_user;
新建的t_user_2表結構定義與源表t_user一致,但是沒有資料
2、在建表的同時插入資料
create table t_access_user
as
select ip,url from t_access;
t_access_user會根據select查詢的欄位來建表,同時將查詢的結果插入新表中
!!!此語句是倒著分析!!!1
5.2.4.桶(bucket)
把表組織成桶有兩個理由:
1.第一個理由是獲得更高的查詢處理效率。桶為表加上了額外的結構。Hive在處理有些查詢時能夠利用這個結構。連線兩個在(包含連線列的)相同列上劃分了桶的表,可以使用map端連線(map-side join)高效地實現。
2.把表劃分成桶的 第二個理由是使“取樣”或者說“取樣”更高效。
使用clustered by 子句來指定劃分桶所用的列 和要劃分的桶的個數:
eg:create table bucketed_users(id int,name string)
clustered by(id) into 4 buckets;
有個沒有劃分桶的使用者表,要向分桶後的表中填充成員,需要將hive.enforce.bucketing屬性設定為true。然後使用insert:
eg:insert overwrite table bucketed_users
select * from users;
用tablesample子句對錶進行取樣:
eg:> select * from bucketed_users
> tablesample(bucket 1 out of 4 on id);
5.3.資料匯入匯出
5.3.1.將資料檔案匯入hive的表
方式1:匯入資料的一種方式:
手動用hdfs命令,將檔案放入表目錄;
Hadoop fs -put w.text /input
方式2:在hive的互動式shell中用hive命令來匯入本地資料到表目錄
hive>load data local inpath '/root/order.data.2' into table t_order;
方式3:用hive命令匯入hdfs中的資料檔案到表目錄
hive>load data inpath '/access.log.2017-08-06.log' into table t_access partition(dt='20170806');
注意:導本地檔案和導HDFS檔案的區別:
本地檔案匯入表:複製
hdfs檔案匯入表:移動
5.3.2.將hive表中的資料匯出到指定路徑的檔案
1、將hive表中的資料匯入HDFS的檔案
insert overwrite directory '/root/access-data'
row format delimited fields terminated by ','
select * from t_access;
2、將hive表中的資料匯入本地磁碟檔案
insert overwrite local directory '/root/access-data'
row format delimited fields terminated by ','
select * from t_access limit 100000;
5.3.3.hive檔案格式
HIVE支援很多種檔案格式: SEQUENCE FILE | TEXT FILE | PARQUET FILE | RC FILE
create table t_pq(movie string,rate int) stored as textfile;
create table t_pq(movie string,rate int) stored as sequencefile;
create table t_pq(movie string,rate int) stored as parquetfile;
演示:
1、先建一個儲存文字檔案的表
create table t_access_text(ip string,url string,access_time string)
row format delimited fields terminated by ','
stored as textfile;
匯入文字資料到表中:
load data local inpath '/root/access-data/000000_0' into table t_access_text;
2、建一個儲存sequence file檔案的表:
create table t_access_seq(ip string,url string,access_time string)
stored as sequencefile;
從文字表中查詢資料插入sequencefile表中,生成資料檔案就是sequencefile格式的了:
insert into t_access_seq
select * from t_access_text;
3、建一個儲存parquet file檔案的表:
create table t_access_parq(ip string,url string,access_time string)
stored as parquetfile;
select * from t_students distribute by sex sort by age;(以男女年齡排序查詢)
方法:
1、執行機制和原理
2、動手:安裝配置
3、寫程式
Hive: 基於HDFS之上的資料倉庫
=======================================
一、什麼是資料倉庫?
1、其實就是一個數據庫(Oracle、MySQL等等)
2、比較大,資料多
3、一般select
二、什麼是Hive?(蜂巢)
1、是基於HDFS之上的資料倉庫
Hive HDFS
表 ----> 目錄
資料 ---> 檔案
分割槽 ---> 目錄
2、是一個翻譯器: SQL ---> Hive ---> MapReduce
舉例: select ---> hive ---> MapReduce程式
三、Hive的體系結構和安裝配置
1、Hive的體系結構
2、Hive的元資訊:表名、列名、列的型別 *****
3、安裝配置(簡單一點)
(*)安裝模式:嵌入模式、本地模式、遠端模式
(*)嵌入模式:
(1)不需要MySQL
(2)自帶Derby資料儲存元資訊
(3)特點:只支援一個連線
(*)本地模式、遠端模式
(1)MySQL資料庫
(2)生產:遠端模式
核心的配置檔案:/root/training/apache-hive-2.3.0-bin/conf/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://localhost:3306/hive?useSSL=false</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>hiveowner</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>Welcome_1</value>
</property>
</configuration>
注意:
Hive-on-MR: 過期了
Hive-on-Spark: 不成熟,還在開發階段
Hive-on-MR is deprecated in Hive 2 and may not be available in the future versions. Consider using a different execution engine (i.e. spark, tez) or using Hive 1.X releases.
四、Hive的資料模型:表(重要)
注意:Hive中,資料預設的分隔符是 tab鍵
1、內部表:類似MySQL中表
hive> create table newemp
> (empno int,
> ename string,
> job string,
> mgr int,
> hiredate string,
> sal int,
> comm int,
> deptno int
> )row format delimited fields terminated by ',';
匯入資料: load
本地資料:load data local inpath '/root/temp/emp.csv' into table newemp;
HDFS: load data inpath '/HDFS的目錄/emp.csv' into table newemp;
2、分割槽表:
hive> create table emp_part
> (empno int,
> ename string,
> job string,
> mgr int,
> hiredate string,
> sal int,
> comm int
> )partitioned by (deptno int)
> row format delimited fields terminated by ',';
3、桶表
4、外部表
5、檢視:
(*)檢視是一個虛表
(*)簡化複雜的查詢
hive> create view newview10
> as
> select * from newemp where deptno=10;
hive> select * from newview10;
7782 CLARK MANAGER 7839 1981/6/9 2450 NULL 10
7839 KING PRESIDENT NULL 1981/11/17 5000 NULL 10
7934 MILLER CLERK 7782 1982/1/23 1300 NULL 10
五、使用JDBC操作Hive
1、JDBC:操作RDBMS的標準介面
1.從本地檔案系統中匯入資料到hive表
(1)資料準備(/home/sopdm/test.dat):
1,wyp,25,13188888888
2,test,30,13899999999
3,zs,34,89931412
(2)首先建立表
use sopdm;
drop table if exists sopdm.wyp;
create table if not exists sopdm.wyp(id int,name string,age int,tel string)
row format delimited
fields terminated by ‘,’
stored as textfile;
(3)從本地檔案系統中匯入資料到Hive表
load data local inpath ‘/home/sopdm/test.dat’ into table sopdm.wyp;
(4)可以到wyp表的資料目錄下檢視,如下命令
dfs -ls /user/sopdm/hive/warehouse/sopdm.db/wyp;
2.從HDFS上匯入資料到Hive表
(1)現在hdfs中建立一個input目錄存放HDFS檔案
hadoop fs -mkdir input; 或 hadoop fs -mkdir /user/sopdm/input;
(2)把本地檔案上傳到HDFS中,並重命名為test_hdfs.dat
hadoop fs -put /home/sopdm/test.dat /user/sopdm/input/test_hdfs.dat;
(3)檢視檔案
dfs -cat /user/sopdm/input/test_hdfs.dat;
(4)將內容匯入hive表中
–拷貝“本地資料”到“hive”使用:load data local…
–轉移“HDFS”到“hive”(必須同一個叢集)使用:load data…
load data inpath ‘/user/sopdm/input/test_hdfs.dat’ into table sopdm.wyp;
3.從別的Hive表中匯入資料到Hive表中
create table if not exists sopdm.wyp2(id int,name string,tel string)
row format delimited
fields terminated by ‘,’
stored as textfile;
–overwrite是覆蓋,into是追加
insert into table sopdm.wyp2
select id,name,tel from sopdm.wyp;
–多表插入
–高效方式-查詢語句插入多個分割槽
from sopdm.wyp w
insert overwrite table sopdm.wyp2
select w.id,w.name,w.tel where w.age=25
insert overwrite table sopdm.wyp2
select w.id,w.name,w.tel where w.age=27;
4.建立Hive表的同時匯入查詢資料
create table sopdm.wyp3
as select id,name,tel,age from sopdm.wyp where age=25;