數據倉庫之Hive

Hive 簡介

  • Hive 數據倉庫
  • Hive 解釋器,編譯器,優化器
  • Hive 運行時,元數據存儲在關係型數據庫裏面

Hive 架構

CLI: command line interface 命令行接口

JDBC/ODBC: Java 連接數據庫(MySQL、Oracle)

Web GUI: Hive web 用戶界面

metastore:表、字段的約束

Driver: Driver 服務,負責 Hadoop 和 Hive 之間的聯繫()

(1)用戶接口主要有三個:CLI,Client 和 WUI。其中最常用的是CLI,Cli啓動的時候,會同時啓動一個Hive副本。Client是Hive的客戶端,用戶連接至Hive Server。在啓動 Client模式的時候,需要指出Hive Server所在節點,並且在該節點啓動Hive Server。 WUI是通過瀏覽器訪問Hive。
(2)Hive將元數據存儲在數據庫中,如mysql、derby。Hive中的元數據包括表的名字,表的列和分區及其屬性,表的屬性(是否爲外部表等),表的數據所在目錄等。
(3)解釋器、編譯器、優化器完成HQL查詢語句從詞法分析、語法分析、編譯、優化以及查詢計劃的生成。生成的查詢計劃存儲在HDFS中,並在隨後有MapReduce調用執行。
(4)Hive的數據存儲在HDFS中,大部分的查詢、計算由MapReduce完成(包含*的查詢,比如select * from tbl不會生成MapRedcue任務)。

Hive 的架構

編譯器將一個Hive SQL轉換操作符
操作符是Hive的最小的處理單元
每個操作符代表HDFS的一個操作或者一道MapReduce作業

Operator

Operator都是hive定義的一個處理過程
Operator都定義有:
protected List <Operator<? extends Serializable >> childOperators;
protected List <Operator<? extends Serializable >> parentOperators;
protected boolean done; // 初始化值爲false

  • ANTER 詞法語法分析工具解析 SQL

Hive 搭建模式

單機模式

通過網絡連接到一個數據庫中

搭建環境準備:

HOST/Soft MySQL Hive
node01 *
hode02 *

搭建過程步驟:

  • 安裝 MySQL

    # 安裝 mysql 服務
    yum install mysql-server -y 
    
    # 輸入 msyql  會出現這樣的錯誤信息, 原因是 mysqld 服務未啓動
    # ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
    
    # 啓動 mysqld 服務
    service mysqld start
    
    # 配置 mysql 遠程連接以及用戶名和密碼
    grant all privileges on *.* to root@'%' identified by '123' with grant option;
    
    # 刷新權限
    flush privileges;
    
    # 刪除 mysql.user 表中的除了遠程連接用戶外其他用戶的記錄
    delete from user where mysql.host != '%'
    
    #  查看 mysql 用戶表
    select host,user,password from mysql.user
    
    
  • 安裝 Hive

  # 安裝 hive
  # 上傳 hive 壓縮包並解壓
tar -zxvf hive.x.y.z.tar.gz
  # 移動到 /opt/sxt 目錄下
  mv  hive.x.y.z  /opt/sxt
  # 配置 hive 環境變量,編輯 vi /etc/profile 文件
  export HIVE_HOME=/opt/sxt/hive.x.y.z
  export PATH=$PATH:$HIVE_HOME/bin
  # 使  /etc/profile 生效
  . /etc/profile
  # 輸入 hive 命令,查看 hive 是否安裝成功
  
  # 修改配置文件
  cp hive-.xml  hive-site.xml  
  vi hive-site.xml
  <property>
      <name>hive.metastore.warehouse.dir</name>
      <value>/user/hive_remote/warehouse</value>
  </property>
  <property>
      <name>javax.jdo.option.ConnectionURL</name>
      <value>jdbc:mysql://node01/hive_remote?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>123</value>
  </property>
  
  # 更新 jar  資源
  # 將 jline.jar 調整爲高版本,同時將 hadoop 的低版本刪除
  cd $HODOOP_HOME/share/hadoop/yarn/lib/ 
  rm -fr jline-0.9.94.jar 
  cp $HIVE_HOME/lib/jline-2.12.jar ./ 
  
  # 啓動
  hive

分佈式模式

用於非Java客戶端訪問元數據庫,在服務器端啓動 MetaStoreServer,客戶端利用 Thrift 協議通過MetaStoreServer訪問元數據庫

搭建環境準備:

mysql hive-server hive-client
node01 *
node03 *
node04 *

搭建步驟:

# 搭建分佈式 Hive 是建立在單機模式之上
# 從之前的 node02 節點上拷貝 $HIVE_HOME 目錄 到 node03、node04 上
# 其中 node03 作爲 Hive 服務端, node04 作爲 Hive 客戶端
scp -r apache-hive-1.2.1-bin/ root@node03:`pwd`/ 
scp -r apache-hive-1.2.1-bin/ root@node04:`pwd`/ 

# 配置 node03 node04 的 HIVE 環境變量

# 更新 jar 資源
# 將 jline.jar 調整爲高版本,同時將 hadoop 的低版本刪除
cd $HODOOP_HOME/share/hadoop/yarn/lib/ 
rm -fr jline-0.9.94.jar 
cp $HIVE_HOME/lib/jline-2.12.jar ./ 

# 在 node03 上 啓動 hive metastore 服務
hive --service metastore
# 在 node04 上啓用 hive 客戶端
hive

配置環境變量的目的:

  1. 找可執行性文件
  2. 方便其他框架或者服務使用。 eg: HIVE 通過 HADOOP 的環境變量連接到 Hadoop 上

Hive 之 DDL

官方文檔地址:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-Overview

DDL 語法

  • 創建表
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name    -- (Note: TEMPORARY available in Hive 0.14.0 and later)
  [(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])]
  [COMMENT table_comment]
  [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
  [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
  [SKEWED BY (col_name, col_name, ...)                  -- (Note: Available in Hive 0.10.0 and later)]
     ON ((col_value, col_value, ...), (col_value, col_value, ...), ...)
     [STORED AS DIRECTORIES]
  [
   [ROW FORMAT row_format] 
   [STORED AS file_format]
     | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)]  -- (Note: Available in Hive 0.6.0 and later)
  ]
  [LOCATION hdfs_path]
  [TBLPROPERTIES (property_name=property_value, ...)]   -- (Note: Available in Hive 0.6.0 and later)
  [AS select_statement];   -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
 
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
  LIKE existing_table_or_view_name
  [LOCATION hdfs_path];
 
data_type
  : primitive_type
  | array_type
  | map_type
  | struct_type
  | union_type  -- (Note: Available in Hive 0.7.0 and later)
 
primitive_type
  : TINYINT
  | SMALLINT
  | INT
  | BIGINT
  | BOOLEAN
  | FLOAT
  | DOUBLE
  | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later)
  | STRING
  | BINARY      -- (Note: Available in Hive 0.8.0 and later)
  | TIMESTAMP   -- (Note: Available in Hive 0.8.0 and later)
  | DECIMAL     -- (Note: Available in Hive 0.11.0 and later)
  | DECIMAL(precision, scale)  -- (Note: Available in Hive 0.13.0 and later)
  | DATE        -- (Note: Available in Hive 0.12.0 and later)
  | VARCHAR     -- (Note: Available in Hive 0.12.0 and later)
  | CHAR        -- (Note: Available in Hive 0.13.0 and later)
 
array_type
  : ARRAY < data_type >
 
map_type
  : MAP < primitive_type, data_type >
 
struct_type
  : STRUCT < col_name : data_type [COMMENT col_comment], ...>
 
union_type
   : UNIONTYPE < data_type, data_type, ... >  -- (Note: Available in Hive 0.7.0 and later)
 
row_format
  : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
        [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
        [NULL DEFINED AS char]   -- (Note: Available in Hive 0.13 and later)
  | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
 
file_format:
  : SEQUENCEFILE
  | TEXTFILE    -- (Default, depending on hive.default.fileformat configuration)
  | RCFILE      -- (Note: Available in Hive 0.6.0 and later)
  | ORC         -- (Note: Available in Hive 0.11.0 and later)
  | PARQUET     -- (Note: Available in Hive 0.13.0 and later)
  | AVRO        -- (Note: Available in Hive 0.14.0 and later)
  | JSONFILE    -- (Note: Available in Hive 4.0.0 and later)
  | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
 
column_constraint_specification:
  : [ PRIMARY KEY|UNIQUE|NOT NULL|DEFAULT [default_value]|CHECK  [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]
 
default_value:
  : [ LITERAL|CURRENT_USER()|CURRENT_DATE()|CURRENT_TIMESTAMP()|NULL ] 
 
constraint_specification:
  : [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name, ...) DISABLE NOVALIDATE 
    [, CONSTRAINT constraint_name UNIQUE (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ]
    [, CONSTRAINT constraint_name CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ]

練習:

create table psn
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':';


load data local inpath '/root/data/data' into table psn;

-- 查看錶結構
desc formatted 表名  

Hive 表

內部表

create table psn3
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by '\001'
collection items terminated by '\002'
map keys terminated by '\003';

外部表

create external table psn4
(
id int,
name string,
likes array<string>,
address map<string,string>
)
row format delimited
fields terminated by ','
collection items terminated by '-'
map keys terminated by ':'
location '/data/hive/input/';

區別*

內部表 MANAGED 外部表 EXTERNAL
創建表時 直接存儲在默認的hdfs路徑 需要自己指定路徑
刪除表時 將數據和元數據全部刪除 只刪除元數據,數據不刪除

先有表,後有數據,使用內部表。先有數據,後有表,使用外部表。

注意:

  1. 刪除外部表中不會刪除 HDFS 中的數據
  2. Hive 讀時檢查(解耦,便於數據讀取); 關係數據庫 寫時檢查

Hive 分區

分區表的意義在於優化查詢。查詢時儘量利用分區字段。如果不使用分區字段,就會全部掃描。

注意:分區屬於元數據,不能通過外部表直接從 HDFS 加載 Hive 中,必須在表定義時指定對應的partition字段

分區建表

a. 單分區建表語句:

create table day_table (id int, content string) partitioned by (dt string);

單分區表,按天分區,在表結構中存在 id,content,dt 三列。
以 dt 爲文件夾區分

b. 雙分區建表語句:

create table day_hour_table (id int, content string) partitioned by (dt string, hour string);

雙分區表,按天和小時分區,在表結構中新增加了 dt 和 hour 兩列。
先以 dt 爲文件夾,再以 hour 子文件夾區分

添加分區表語法

(表已創建,在此基礎上添加分區):
ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION ‘location1’] partition_spec [LOCATION ‘location2’] …;

partition_spec:
(partition_column = partition_col_value, partition_column = partition_col_value, …)
例:
ALTER TABLE day_table ADD PARTITION (dt='2008-08-08', hour='08')

刪除分區

LTER TABLE table_name DROP partition_spec, partition_spec,…
partition_spec:
: (partition_column = partition_col_value, partition_column = partition_col_value, …)

用戶可以用 ALTER TABLE DROP PARTITION 來刪除分區。
內部表中、對應分區的元數據和數據將被一併刪除。

例:

ALTER TABLE day_hour_table DROP PARTITION (dt='2008-08-08', hour='09');

向指定分區添加數據語法

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] 
INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] 

例:

-- 從 HDFS 中加載數據
LOAD DATA INPATH '/user/pv.txt' 
INTO TABLE day_hour_table PARTITION(dt='2008-08- 08', hour='08'); 

-- 從本地文件系統中加載數據
LOAD DATA local INPATH '/user/hua/*' 
INTO TABLE day_hour partition(dt='2010-07- 07');

當數據被加載至表中時,不會對數據進行任何轉換。

Load 操作只是將數據複製至 Hive 表對應的位置。數據加載時在表下自動創建一個目錄

查詢執行分區語法

SELECT day_table.* FROM day_table WHERE day_table.dt>= '2008-08-08'; 

分區表的意義在於優化查詢。查詢時儘量利用分區字段。如果不使用分區字段,就會全部掃描。

Hive查詢表的分區信息語法

SHOW PARTITIONS day_hour_table; 

預先導入分區數據,但是無法識別怎麼辦?

Msck repair table tablename

直接添加分區

動態分區

  • 開啓支持動態分區

    set hive.exec.dynamic.partition=true;
    

    默認:true

    set hive.exec.dynamic.partition.mode=nostrict;
    

    默認:strict(至少有一個分區列是靜態分區)
    相關參數

    set hive.exec.max.dynamic.partitions.pernode;
    

    每一個執行mr節點上,允許創建的動態分區的最大數量(100)

    set hive.exec.max.dynamic.partitions;	
    

    所有執行mr節點上,允許創建的所有動態分區的最大數量(1000)

    set hive.exec.max.created.files;
    

    所有的mr job允許創建的文件的最大數量(100000)

  • 加載數據

    create external table psn21(
    id int,
    name string,
    sex string,
    age int,
    likes array<string>,
    address map<string,string>
    )
    row format delimited
    fields terminated by ','
    collection items terminated by '-'
    map keys terminated by ':'
    location '/data/bucket/input';
    
    
    create table psn22(
    id int,
    name string,
    likes array<string>,
    address map<string,string>
    )
    partitioned by (age int,sex string) 
    row format delimited
    fields terminated by ','
    collection items terminated by '-'
    map keys terminated by ':';
    
    # hive 命令行中設置動態分區爲非嚴格模式
    set hive.exec.dynamic.partition.mode=nonstrict
    
    # 注意: 參數的位置要對應
    from psn21
    insert overwrite table psn22 partition(age, sex)  
    select id, name, likes, address, age,sex distribute by age, sex;
    

Hive 之 DML*

官方文檔地址:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML#LanguageManualDML-HiveDataManipulationLanguage

加載數據的方式

  • Loading files into tables 從文件中加載數據

    Hive does not do any transformation while loading data into tables. Load operations are currently pure copy/move operations that move datafiles into locations corresponding to Hive tables.

    語法:

    LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] 
    INTO TABLE tablename 
    [PARTITION (partcol1=val1, partcol2=val2 ...)]
    
    LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] 
    INTO TABLE tablename 
    [PARTITION (partcol1=val1, partcol2=val2 ...)] 
    [INPUTFORMAT 'inputformat' SERDE 'serde'] (3.0 or later)
    

    注意: 從 HDFS 中加載數據,數據發生移動,而從本地加載數據,數據發生拷貝。

  • Inserting data into Hive Tables from queries 從查詢結果集中加載數據

Query Results can be inserted into tables by using the insert clause.

語法:

Standard syntax:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
 
Hive extension (multiple inserts):
FROM from_statement
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2]
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...;
FROM from_statement
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1
[INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2]
[INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2] ...;
 
Hive extension (dynamic partition inserts):
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;

例子:

FROM psn
INSERT OVERWRITE TABLE psn10
SELECT id,name
insert into psn11
select id,likes 

insert overwrite local directory '/root/result' 
select * from psn;

更新操作

  • ACID 事務的特性
  • 三大範式

Hive SerDe

SerDe 用於做序列化和反序列化。

構建在數據存儲和執行引擎之間,對兩者實現解耦。
Hive通過 ROW FORMAT DELIMITED 以及 SERDE 進行內容的讀寫。

row_format
: DELIMITED 
          [FIELDS TERMINATED BY char [ESCAPED BY char]] 
          [COLLECTION ITEMS TERMINATED BY char] 
          [MAP KEYS TERMINATED BY char] 
          [LINES TERMINATED BY char] 
: SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]

Hive 正則匹配

CREATE TABLE logtbl (
    host STRING,
    identity STRING,
    t_user STRING,
    time STRING,
    request STRING,
    referer STRING,
    agent STRING)
  ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
  WITH SERDEPROPERTIES (
    "input.regex" = "([^ ]*) ([^ ]*) ([^ ]*) \\[(.*)\\] \"(.*)\" (-|[0-9]*) (-|[0-9]*)"
  )
  STORED AS TEXTFILE;

Hive Beeline

提供了 JDBC 的訪問方式

beenline 不能用於 DML 操作,只能執行一些查詢操作

-- 第一種方式
beeline 
!connect jdbc:hive2://node04:10000/default root 123

-- 第二種方式
beeline -u connect jdbc:hive2://node04:10000/default -n root 

Hive JDBC

public class HiveDemo {
	
//	private final static String driver = "org.apache.hive.jdbc.HiveDriver";
//	private final static String url = "jdbc:hive2://node04:10000/default";
//	private final static String username = "root";
//	private final static String password = "123";
	
	public static void main(String[] args) {
		try {
			Properties prop = new Properties();
			prop.load(new FileInputStream(new File("jdbc.properties")));
			String driver = prop.getProperty("driver");
			String url = prop.getProperty("url");
			String username = prop.getProperty("username");
			String password = prop.getProperty("password");
            
			Class.forName(driver);
			Connection conn = DriverManager.getConnection(url,username,password);
			Statement st = conn.createStatement();
			String sql = "select * from psn";
			ResultSet rs = st.executeQuery(sql);
			while(rs.next()){
				int id = rs.getInt("id");
				String name = rs.getString("name");
				System.out.println(id+"\t"+name);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Hive 函數

官方文檔地址:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

自定義 UDF

官方文檔地址:

https://cwiki.apache.org/confluence/display/Hive/HivePlugins

  • java 代碼
public class TuoMing extends UDF{
	
	public Text evaluate(final Text s) {
		if (s == null) {
			return null;
		}
		String str = s.toString().substring(0, 3) + "***";
		return new Text(str);
	}
}
  • 將 java 代碼文件打包成 jar ,上傳 Linux 上的 HDFS 中

  • 創建臨時函數

    -- 本地文件系統加載
    add jar /root/tm/tm.jar;
    create temporary function tm as 'com.szxy.hive.TuoMing';
    
    -- 從 HDFS 中加載
    create temporary function tms as 'com.szxy.hive.TuoMing' 
    using jar 'hdfs://node01:8020/data/jar/tm/tm.jar';
    
  • 使用臨時函數

    select tms(name) from psn;
    
  • 結果

Hive 案例

struct 結構體

  • 測試數據

    1001,zhangsan:24
    1002,lisi:25
    1003,wangwu:26
    1004,zhaoliu:27
    
  • 創建表

    create table student(
    id int,
    info struct<name:string,age:int>)
    row format delimited 
    fields terminated by "," 
    collection items terminated by ":";
    
    load data inpath '/data/struct/input' into table student;
    

WordCount

create external table hello(
line string 
)
location '/data/wc/input'

create table hello_wc(
word string ,
num int 
);

from (select explode(split(line,' ')) word from hello ) t 
insert into hello_wc 
select word,count(word) group by word;

基站掉話率統計

  • 需求:

    找出掉線率最高的前10基站

  • sql 語句

    create table tb_cell_result(
    imei string,
    drop_num int,
    duration int,
    drop_rate double
    );
    
    create external table tb_cell(
    record_time string,
    imei string,
    cell string,
    ph_num int,
    call_num string,
    drop_num int,
    duration int,
    drop_rate int,
    net_type string,
    erl int 
    )
    row format delimited fields terminated by ','
    location '/data/cell/input';
    
    from tb_cell 
    insert into tb_cell_result
    select imei,sum(drop_num) sdrop,sum(duration) sdura, sum(drop_num)/sum(duration) srate group by imei sorted by srate desc;
    
    select * from tb_cell_result limit 10;
    
    

Hive 參數

  • hive 參數、變量

    hive當中的參數、變量,都是以命名空間開頭

    命名空間 讀寫權限 含義
    hiveconf 可讀寫 hive-site.xml 中配置各種變量
    例:hive --hiveconf hive.cli.print.header=true
    System 可讀寫 系統變量,包括 JVM 運行參數等
    例:system:user.name=root
    env 只讀 環境變量“
    例:env:JAVA_HOME
    hivevar 可讀寫 例:hive -d val=key

    通過 ${} 方式進行引用,其中 system、env 下的變量必須以前綴開頭

  • hive 參數設置方式

    1. 修改配置文件 ${HIVE_HOME}/conf/hive-site.xml

      <property>
       <name>hive.cli.print.header</name>
       <value>true</value>
      </property>
      
    2. 啓動 hive cli 時,通過 --hiveconf key=value的方式進行設置

      ​ 例:hive --hiveconf hive.cli.print.header=true

    3. 進入cli之後,通過使用set命令設置

      set hive.cli.print.header=true;
      

Hive 分桶

分桶概念

  • 分桶表是對列值取哈希值的方式,將不同數據放到不同文件中存儲。

  • 對於hive中每一個表、分區都可以進一步進行分桶。

  • 由列的哈希值除以桶的個數來決定每條數據劃分在哪個桶中。

適用場景

數據抽樣( sampling )

分桶操作

  • 開啓支持分桶

    set hive.enforce.bucketing=true;
    

    默認:false;設置爲 true之後,mr運行時會根據 bucket 的個數自動分配 reduce task 個數。

    (用戶也可以通過mapred.reduce.tasks自己設置reduce任務個數,但分桶時不推薦使用)
    注意:一次作業產生的桶(文件數量)和reduce task個數一致。

  • 往分桶表中加載數據

    insert into table bucket_table select columns from tbl;
    insert overwrite table bucket_table select columns from tbl;
    
  • 桶表 抽樣查詢

    select * from bucket_table tablesample(bucket 1 out of 4 on columns);
    
  • TABLESAMPLE 語法

    TABLESAMPLE(BUCKET x OUT OF y)
    

    x:表示從哪個bucket開始抽取數據
    y:必須爲該表總bucket數的倍數或因子

  • 栗子
    當表總 bucket 數爲32時

    TABLESAMPLE(BUCKET 3 OUT OF 8),抽取哪些數據?

    答:共抽取2(32/16)個bucket的數據,抽取第2、第18(16+2)個bucket的數據

    TABLESAMPLE(BUCKET 3 OUT OF 256),抽取哪些數據?

分桶案例

  • 測試數據

    1,tom,11
    2,cat,22
    3,dog,33
    4,hive,44
    5,hbase,55
    6,mr,66
    7,alice,77
    8,scala,88
    
  • 創建 hive 表

    create external table tb_bucket(
    id int,
    name string,
    score int
    )
    row format delimited 
    fields terminated by ','
    location '/data/bucket/input';
    
  • 創建分桶表

    create table psn_bucket(
    id int,
    name string,
    score int
    )
    clustered by(score) into 4 buckets
    row format delimited
    fields terminated by ',';
    
  • 向分桶表中添加數據

    insert into psn_bucket select id,name,score from tb_bucket;
    

    注意:Hive 分桶默認是關閉的,通過 set hive.enforce.bucketing=true;開啓分桶

  • 抽樣

     select id,name,score from psn_bucket tablesample(bucket 2 out of 4);
    

Hive Laternal View

在 UDTF 函數中使用

Lateral View用於和UDTF函數(explode、split)結合來使用。
首先通過UDTF函數拆分成多行,再將多行結果組合成一個支持別名的虛擬表。
主要解決在select使用UDTF做查詢過程中,查詢只能包含單個UDTF,不能包含其他字段、以及多個UDTF的問題

語法:

LATERAL VIEW udtf(expression) tableAlias AS columnAlias (',' columnAlias)

注意: 列別名有多個,並且可以重複

栗子

統計人員表中共有多少種愛好、多少個城市?

select count(distinct(myCol1)), count(distinct(myCol2)) from psn
LATERAL VIEW explode(likes) myTable1 AS myCol1 
LATERAL VIEW explode(address) myTable2 AS myCol2, myCol3;  

select count(distinct(mycol)) from psn lateral view explode(likes)  myTable as mycol;

Hive 視圖

視圖本質上就是一個虛擬表 Virtual Table,和關係型數據庫中的普通視圖一樣,hive也支持視圖

特點:

  • 不支持物化視圖

  • 只能查詢,不能做加載數據操作

  • 視圖的創建,只是保存一份元數據,查詢視圖時才執行對應的子查詢

  • view定義中若包含了ORDER BY/LIMIT語句,當查詢視圖時也進行ORDER BY/LIMIT語句操作,view當中定義的優先級更高

  • view支持迭代視圖

view語法

  • 創建視圖:

    CREATE VIEW [IF NOT EXISTS] [db_name.]view_name 
      [(column_name [COMMENT column_comment], ...) ]
      [COMMENT view_comment]
      [TBLPROPERTIES (property_name = property_value, ...)]
      AS SELECT ... ;
    
  • 查詢視圖:

    select colums from view;
    
  • 刪除視圖:

    DROP VIEW [IF EXISTS] [db_name.]view_name
    

Hive 索引

  • 目的

    優化查詢以及檢索性能

  • 創建索引:

    create index t1_index on table psn(name) 
    as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' 
    with deferred rebuild 
    in table t1_index_table;
    -- as:指定索引器;
    -- in table:指定索引表,若不指定默認生成在default__psn2_t1_index__表中
    
    create index t1_index on table psn2(name) 
    as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' 
    with deferred rebuild;
    
  • 查詢索引

    show index on psn2;
    
  • 重建索引(建立索引之後必須重建索引才能生效)

    ALTER INDEX t1_index ON psn REBUILD;
    
  • 刪除索引

    DROP INDEX IF EXISTS t1_index ON psn;
    

Hive 運行方式

  1. 命令行方式cli:控制檯模式

    • 與hdfs交互
      執行執行dfs命令
      例:dfs –ls /
    • 與Linux交互
      !開頭
      例:!pwd
  2. 腳本運行方式(實際生產環境中用最多)

    hive -e ""
    hive -e "">aaa
    hive -S -e "">aaa
    hive -f file
    hive -i /home/my/hive-init.sql
    hive> source file (在hive cli中運行)
    
  3. JDBC方式:hiveserver2

  4. web GUI接口 (hwi、hue等)

Hive 權限管理

官方文檔地址:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Authorization

三種授權模型:

  1. Storage Based Authorization in the Metastore Server

    基於存儲的授權 - 可以對Metastore中的元數據進行保護,但是沒有提供更加細粒度的訪問控制(例如:列級別、行級別)。

  2. SQL Standards Based Authorization in HiveServer2

    基於SQL標準的Hive授權 - 完全兼容SQL的授權模型,推薦使用該模式。
    https://cwiki.apache.org/confluence/display/Hive/SQL+Standard+Based+Hive+Authorization

  3. Default Hive Authorization (Legacy Mode)
    hive默認授權 - 設計目的僅僅只是爲了防止用戶產生誤操作,而不是防止惡意用戶訪問未經授權的數據。

SQL Standards Based Authorization in HiveServer2

  • 完全兼容SQL的授權模型

  • 除支持對於用戶的授權認證,還支持角色 role 的授權認證

    role可理解爲是一組權限的集合,通過role爲用戶授權

    一個用戶可以具有一個或多個角色

    默認包含另種角色:public、admin

  • 限制:
    1、啓用當前認證方式之後,dfs, add, delete, compile, and reset等命令被禁用。

    2、通過set命令設置hive configuration的方式被限制某些用戶使用。

    (可通過修改配置文件hive-site.xml中hive.security.authorization.sqlstd.confwhitelist進行配置)

    3、添加、刪除函數以及宏的操作,僅爲具有admin的用戶開放。

    4、用戶自定義函數(開放支持永久的自定義函數),可通過具有admin角色的用戶創建,其他用戶都可以使用。

    5、Transform功能被禁用。

  • 在hive服務端修改配置文件hive-site.xml添加以下配置內容

    <property>
      <name>hive.security.authorization.enabled</name>
      <value>true</value>
    </property>
    <property>
      <name>hive.server2.enable.doAs</name>
      <value>false</value>
    </property>
    <property>
      <name>hive.users.in.admin.role</name>
      <value>root</value>
    </property>
    <property>
      <name>hive.security.authorization.manager</name>
      <value>org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory</value>
    </property>
    <property>
      <name>hive.security.authenticator.manager</name>
      <value>org.apache.hadoop.hive.ql.security.SessionStateUserAuthenticator</value>
    </property>
    

    服務端啓動hiveserver2;客戶端通過beeline進行連接

Hive 優化*

核心思想:把 Hive SQL 當做Mapreduce程序去優化

以下 SQL 不會轉爲Mapreduce來執行:

  1. select 僅查詢本表字段

  2. where 僅對本表字段做條件過濾

Explain 顯示執行計劃

EXPLAIN [EXTENDED] query

Hive抓取策略

Hive中對某些情況的查詢不需要使用 MapReduce 計算

抓取策略

Set hive.fetch.task.conversion=none/more;

Hive運行方式

  • 本地模式

  • 集羣模式

開啓本地模式

set hive.exec.mode.local.auto=true;

注意:
hive.exec.mode.local.auto.inputbytes.max 默認值爲128M
表示加載文件的最大值,若大於該配置仍會以集羣方式來運行

並行計算

通過設置以下參數開啓並行模式:

set hive.exec.parallel=true;

注意:hive.exec.parallel.thread.number
(一次SQL計算中允許並行執行的job個數的最大值)

嚴格模式

  • 通過設置以下參數開啓嚴格模式:
set hive.mapred.mode=strict;

(默認爲:nonstrict非嚴格模式)

  • 查詢限制

    1、對於分區表,必須添加where對於分區字段的條件過濾;

    2、order by語句必須包含limit輸出限制;

    3、限制執行笛卡爾積的查詢。

Hive排序

  • Order By - 對於查詢結果做全排序,只允許有一個reduce處理
    (當數據量較大時,應慎用。嚴格模式下,必須結合limit來使用)
  • Sort By - 對於單個reduce的數據進行排序
  • Distribute By - 分區排序,經常和Sort By結合使用
  • Cluster By - 相當於 Sort By + Distribute By
    (Cluster By不能通過asc、desc的方式指定排序規則;
    可通過 distribute by column sort by column asc|desc 的方式)

Hive Join

Join計算時,將小表(驅動表)放在join的左邊

Map Join:在Map端完成Join

兩種實現方式:

  1. SQL方式,在SQL語句中添加 MapJoin 標記(mapjoin hint)
    語法:
SELECT  /*+ MAPJOIN(smallTable) */  smallTable.key,  bigTable.value 
FROM  smallTable  JOIN  bigTable  ON  smallTable.key  =  bigTable.key;
  1. 開啓自動的MapJoin

    自動的mapjoin
    通過修改以下配置啓用自動的 mapjoin:

    set hive.auto.convert.join = true;
    

    (該參數爲true時,Hive 自動對左邊的表統計量,如果是小表就加入內存,即對小表使用 Map join)

    相關配置參數:

    hive.mapjoin.smalltable.filesize; 
    

    (大表小表判斷的閾值,如果表的大小小於該值則會被加載到內存中運行)

    hive.ignore.mapjoin.hint;
    

    (默認值:true;是否忽略mapjoin hint 即mapjoin標記)

    hive.auto.convert.join.noconditionaltask;
    

    (默認值:true;將普通的join轉化爲普通的mapjoin時,是否將多個mapjoin轉化爲一個mapjoin)

    hive.auto.convert.join.noconditionaltask.size;
    

    (將多個mapjoin轉化爲一個mapjoin時,其表的最大值)

    注意:hive.exec.parallel.thread.number(一次SQL計算中允許並行執行的job個數的最大值)

    • 儘可能使用相同的連接鍵(會轉化爲一個MapReduce作業)
  • 大表join大表

    空key過濾:有時join超時是因爲某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠。此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據,我們需要在SQL語句中進行過濾。
    空key轉換:有時雖然某個key爲空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中,此時我們可以表a中key爲空的字段賦一個隨機的值,使得數據隨機均勻地分不到不同的reducer上

Map-Side聚合

通過設置以下參數開啓在Map端的聚合:

set hive.map.aggr=true;

相關配置參數:

hive.groupby.mapaggr.checkinterval: 

map 端 group by 執行聚合時處理的多少行數據(默認:100000)

hive.map.aggr.hash.min.reduction: 

進行聚合的最小比例(預先對100000條數據做聚合,若聚合之後的數據量/100000的值大於該配置0.5,則不會聚合)

hive.map.aggr.hash.percentmemory: 

map端聚合使用的內存的最大值

hive.map.aggr.hash.force.flush.memory.threshold: 

map端做聚合操作是hash表的最大可用內容,大於該值則會觸發flush

hive.groupby.skewindata

是否對GroupBy產生的數據傾斜做優化,默認爲false

相關配置參數:

hive.groupby.mapaggr.checkinterval: 

map端group by執行聚合時處理的多少行數據(默認:100000)

hive.map.aggr.hash.min.reduction: 

進行聚合的最小比例(預先對100000條數據做聚合,若聚合之後的數據量/100000的值大於該配置0.5,則不會聚合)

hive.map.aggr.hash.percentmemory: 

map端聚合使用的內存的最大值

hive.map.aggr.hash.force.flush.memory.threshold: 

map端做聚合操作是hash表的最大可用內容,大於該值則會觸發flush

hive.groupby.skewindata

是否對GroupBy產生的數據傾斜做優化,默認爲false

合併小文件

文件數目小,容易在文件存儲端造成壓力,給hdfs造成壓力,影響效率

  • 設置合併屬性

    是否合併map輸出文件:hive.merge.mapfiles=true
    是否合併reduce輸出文件:hive.merge.mapredfiles=true;
    合併文件的大小:hive.merge.size.per.task=25610001000

  • 去重統計

    數據量小的時候無所謂,數據量大的情況下,由於 COUNT DISTINCT 操作需要用一個 Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換

控制Hive中Map以及Reduce的數量

  • Map 數量相關的參數

    參數設置 解釋
    mapred.max.split.size 一個split的最大值,即每個map處理文件的最大值
    mapred.min.split.size.per.node 一個節點上split的最小值

| mapred.min.split.size.per.rack | 一個機架上split的最小值 |

  • Reduce 數量相關的參數
    參數 解釋
    mapred.reduce.tasks 強制指定reduce任務的數量
    hive.exec.reducers.bytes.per.reducer 每個reduce任務處理的數據量
    hive.exec.reducers.max 每個任務最大的reduce數

Hive- JVM重用

適用場景:
1、小文件個數過多
2、task個數過多

通過 set mapred.job.reuse.jvm.num.tasks=n;來設置
(n爲task插槽個數)

缺點:

設置開啓之後,task插槽會一直佔用資源,不論是否有task運行,

直到所有的 task 即整個 job 全部執行完成時,纔會釋放所有的 task 插槽資源!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章