Hive - 文件存儲、文件壓縮、視圖、日誌、運行方式、JDBC、優化

一、文件存儲格式

File Formats and Compression: RCFile, Avro, ORC, Parquet; Compression, LZO

1.1 textfile

1、textfile是hive默認的數據文件存儲格式
2、textfile是普通的文件文本存儲
3、不壓縮
4、可以配合壓縮配置屬性進行壓縮
CREATE TABLE `u4`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as textfile;

set mapreduce.output.fileoutputformat.compress=true;
set hive.exec.compress.output=true;
insert into table u4
select * from u2;

1.2 sequencefile

1、sequencefile是hive爲用戶提供的二進制存儲
2、sequencefile不能使用load方式直接加載數據
3、本身壓縮
CREATE TABLE `u4`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as sequencefile;

1.3 rcfile

1、rcfile是hive爲用戶提供的行列混合存儲
2、rcfile格式下,將會盡量把附近的行和列的塊儘量存儲到一起
3、本身壓縮,且查詢效率較高
CREATE TABLE `u5`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as rcfile;

1.4 orc

1、orc是優化後的rcfile
CREATE TABLE `u6`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as orc;

1.5 parquet

1、parquet是典型列式存儲,自帶壓縮,查詢較快(按列查詢)
CREATE TABLE `u7`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as PARQUET;
insert into table u7
select * from u2;

1.6 自定義存儲格式

數據:
seq_yd元數據文件:
aGVsbG8gemhhbmdoYW8=
aGVsbG8gZmVpZmVpLGdvb2QgZ29vZCBzdHVkeSxkYXkgZGF5IHVw
seq_yd文件爲base64編碼後的內容,decode後數據爲:

hello zhanghao
hello feifei,good good study,day day up

create table cus(str STRING)  
stored as  
inputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextInputFormat'  
outputformat 'org.apache.hadoop.hive.contrib.fileformat.base64.Base64TextOutputFormat';  

LOAD DATA LOCAL INPATH '/home/hivedata/cus' INTO TABLE cus;

配置文件相關內容

hive-default.xml.template

<property>
    <name>hive.default.fileformat</name>
    <value>TextFile</value>
    <description>
      Expects one of [textfile, sequencefile, rcfile, orc].
      Default file format for CREATE TABLE statement. Users can explicitly override it by CREATE TABLE ... STORED AS [FORMAT]
    </description>
  </property>

二、文件壓縮

2.1 map輸出壓縮

mapreduce.map.output.compress=false
mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

2.2 reduce輸出壓縮(reduce壓縮)

snappy、bzip2、gzip、DefaultCompress
mapreduce.output.fileoutputformat.compress=false
mapreduce.output.fileoutputformat.compress.type=NONE/RECORD/BLOCK(默認RECORD)
mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

2.3 壓縮配置

set hive.exec.compress.output=false;
set hive.exec.compress.intermediate=false;
set hive.intermediate.compression.codec=
set hive.intermediate.compression.type=


CREATE TABLE `u4`(
  `id` int,
  `name` string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
stored as textfile;

set mapreduce.output.fileoutputformat.compress=true;
set hive.exec.compress.output=true;
insert into table u4
select * from u2;

2.4 壓縮算法

snappy、bzip2、gzip、DefaultCompress

2.5 lzo壓縮(未完成)

2.6 snaapy壓縮(未完成)

三、Hive視圖

3.1 視圖簡介

hive的視圖簡單理解爲邏輯上的表
hive現目前只支持邏輯視圖,不支持物化視圖。

hive的視圖意義:
1、對數據進行局部暴露(涉及隱私數據不暴露)。
2、簡化複雜查詢。

3.2 創建視圖

create view if not exists tab_v1 
as 
select id from u2;

3.3 查看視圖

show tables;
show create table tab_v1;
desc tab_v1;

3.4 刪除視圖

drop view if exists tab_v2;
drop table if exists tab_v1;   (drop是刪除表,不能用於刪除視圖)

3.5 注意事項

1、不建議先刪除視圖對應的表後再查詢視圖。
2、視圖是不能用insert into 或者load 方式來加載數據。
3、視圖是隻讀,不能修改其結構、表相關屬性。

四、Hive日誌

4.1 Hive的系統日誌

默認目錄:/tmp/{user.name}
hive.log.dir={java.io.tmpdir}/{user.name}
hive.log.file=hive.log

4.2 Hive的查詢日誌

// hive-default.xml.template
<property>
    <name>hive.querylog.location</name>
    <value>${system:java.io.tmpdir}/${system:user.name}</value>
    <description>Location of Hive run time structured log file</description></property>

五、Hive運行方式

beeline的配置

5.1 Hive的屬性設置

1、hive-site.xml
2、hive通過命令行參數設置
3、hive通過cli端set設置

5.2 三種設置方式的區別

1、屬性設置優先級從上往下依次升高
2、hive-site.xml是全局和永久的,其它兩個是臨時和局部的
3、hive-site.cml適合所有屬性配置,而後兩個對於系統級別的屬性不能配置,比如啓動所需的元數據庫url、log的配置等。

5.3 Hive的四類屬性

hiveconf:可讀可寫
hivevar:自定義臨時變量,可讀可寫
system:可讀可寫
env:可讀不可寫

--hiveconf <property=value>   Use value for given property
--hivevar <key=value>         Variable subsitution to apply to hive
                                  commands. e.g. --hivevar A=B
hive -e
hive -f
hive -S		靜音模式
hive -i
hive --database 

hive>set -v;  ##查看hive相關的環境變量
hive -e "set" | grep current   ##單個查找	

5.4 Hive的三種運行方式

在hive的cli端運行:(開發測試,以及臨時跑作業)
通過命令行 hive -e 'sql query';
通過命令行 hive -f /hql文件   (生產線)

hive --database qf1701 -e 'select * from text1';
hive --database qf1701 --hivevar ls=2 --hiveconf tn=text1 -e 'select * from ${hiveconf:tn} limit ${hivevar:ls}';

hive -S --hivevar mapoutputdir=/home/hivedata/out/05 --hivevar textoutdir=/home/hivedata/out/06 --hivevar limit=1 -f ./hql

注意:
1、一個--hivevar 或者 --hiveconf 只能帶一個參數
2、--hiveconf 或者 --hivevar 可以混合使用
3、--hiveconf 或 --hivevar 定義參數不能取消

六、Hive的遠程模式使用

hive也可以啓動爲一個服務器,來對外提供

啓動方式,(假如是在hadoop01上):
啓動爲前臺:bin/hiveserver2
啓動爲後臺:nohup bin/hiveserver2 1>/var/log/hiveserver.log 2>/var/log/hiveserver.err &

啓動成功後,可以在別的節點上用beeline去連接
方式(1)
hive/bin/beeline  回車,進入beeline的命令界面
輸入命令連接hiveserver2
beeline> !connect jdbc:hive2://hdp01:10000
(hdp01是hiveserver2所啓動的那臺主機名,端口默認是10000)
方式(2)
或者啓動就連接:
bin/beeline -u jdbc:hive2://hdp01:10000 -n hadoop

接下來就可以做正常sql查詢了

七、Hive的JDBC

7.1 實例

pom.xml

 <!-- https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc -->
<dependency>
	<groupId>org.apache.hive</groupId>
	<artifactId>hive-jdbc</artifactId>
	<version>1.2.1</version>
</dependency>

HiveJdbc.java

package HiveJdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import util.HiveJdbcUtil;

/**
 * hive的連接
 */
public class HiveJDBC {
    private static Connection conn = null;
    public static void main(String[] args) {
        selectDemo();
    }

    //查詢某天某公司的員工數量
    public static void selectDemo(){
        conn = HiveJdbcUtil.getConn();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            //獲取ps
            ps = conn.prepareStatement("select \n" +
                    "*\n" +
                    "from t1 \n");
            //爲佔位符賦值
//            ps.setInt(1,1);
            //執行查詢
            rs = ps.executeQuery();
            //遍歷結果集
            while (rs.next()){
                System.out.println(rs.getString(1) + "\t"
                        + rs.getString(2) + "\t" + rs.getString(3));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            HiveJdbcUtil.closeConn(conn,ps,rs);

        }
    }

}

HiveJdbcUtil.java

package util;

import java.sql.*;

/**
 * 連接工具類
 */
public class HiveJdbcUtil {
    private static String driverName = "org.apache.hive.jdbc.HiveDriver";
    private static String url = "jdbc:hive2://hadoop01:10000/leo"; //指定數據庫爲dw_hivedata
    private static String userName = "root"; //hiveserver2的用戶名和密碼
    private static String password = "123456";
    public static void main(String[] args) {
        System.out.println(getConn());
    }

    /**
     *獲取hive的驅動連接
     * @return
     */
    public static Connection getConn(){
        Connection conn = null;
        try {
            Class.forName(driverName); //加載驅動
            //獲取conn
            conn = DriverManager.getConnection(url, userName, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (SQLException e){
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 關閉連接
     * @param conn
     */
    public static void closeConn(Connection conn, PreparedStatement ps , ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(ps != null){
            try {
                ps.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn != null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

7.2 注意

1、conn、ps\rs的關閉順序需要時rs\ps\conn,否則報錯sasl
2、連接的用戶名和密碼需要 填寫,如果沒有配置可以使用root、root,否則會報錯沒有權限。

7.3 優化

kylin:加速hive的查詢(將查詢預執行,並將結果保存在Hbase中)

八、Hive的優化

1、考慮環境(硬件服務器、配置)
2、業務	(統計指標的實現思路)
3、代碼或者配置屬性

8.1、explain 和 explain extended

explain select * from text1;
explain extended select * from text1;
explain extended
select
d.deptno as deptno,
d.dname as dname
from dept d
union all
select
d.dname as dname,
d.deptno as deptno
from dept d
;
explain : 只有對hql語句的解釋。
explain extended:對hql語句的解釋,以及抽象表達式樹的生成。

stage 相當於一個job,一個stage可以是limit、也可以是一個子查詢、也可以是group by等。
hive默認一次只執行一個stage,但是如果stage之間沒有相互依賴,將可以並行執行。
任務越複雜,hql代碼越複雜,stage越多,運行的時間一般越長。

8.2、join

hive的查詢永遠是小表(結果集)驅動大表(結果集)
hive中的on的條件只能是等值連接
注意hive是否配置普通join轉換成map端join、以及mapjoin小表文件大小的閥值
注意hive的傾斜join:

8.3、limit的優化

hive.limit.row.max.size=100000
hive.limit.optimize.limit.file=10
hive.limit.optimize.enable=false  (如果limit較多時建議開啓)
hive.limit.optimize.fetch.max=50000

8.4、本地模式

hive.exec.mode.local.auto=false (建議打開)
hive.exec.mode.local.auto.inputbytes.max=134217728(128M)
hive.exec.mode.local.auto.input.files.max=4

8.5、並行執行

hive.exec.parallel=false   (建議開啓)
hive.exec.parallel.thread.number=8

8.6、嚴格模式

hive.mapred.mode=nonstrict

Cartesian Product.
No partition being picked up for a query.
Orderby without limit.
Comparing bigints and strings.
Comparing bigints and doubles.

select
e.*
from dept d 
join emp e
;

select
e.*
from emp e
order by e.empno desc
;

create table text9 (
uid bigint, 
uid1 double
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
;

LOAD DATA LOCAL INPATH '/home/hivedata/text8' INTO TABLE text9;

select

- from text9 t
  where t.uid = t.uid1
  ;

8.7、mapper和reducer的個數

不是mapper和redcuer個數越多越好,也不是越少越好,適合即可。

將小文件合併處理(將輸入類設置爲:CombineTextInputFormat)
通過配置將小文件合併:
mapred.max.split.size=256000000   
mapred.min.split.size.per.node=1
mapred.min.split.size.per.rack=1
hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

手動設置:
set mapred.map.tasks=2;

reducer的個數(自動決定和手動設置):
mapred.reduce.tasks=-1
hive.exec.reducers.max=1009

8.8、配置jvm重用

mapreduce.job.jvm.numtasks=1   ###
mapred.job.reuse.jvm.num.tasks=1

8.9、數據傾斜

由於key分佈不均勻造成的數據向一個方向偏離的現象
join語句、count(distinct col)、group by都認識容易造成數據傾斜的

傾斜現象:
卡在某一個reduce任務

解決方法:
1、找到造成數據傾斜的key,然後再通過hql語句避免(查看日誌是那個task失敗-->找到該task關聯字段、group by\count(distrinct col)-->抽樣字段個數-->判斷是否是傾斜的key)。單獨拿出來處理,然後再和正常的結果進行union all

2、造成傾斜的key加隨機數(加的隨機不能造成二次傾斜、保證加隨機不能影響原有的業務)

3、設置相關傾斜的屬性
hive.map.aggr=true;
hive.groupby.skewwindata=false;(建議開啓)
hive.optimize.skewjoin=false;

4、如上都不行,則需要重新查看業務,優化語句流程

8.10、索引

索引是一種hive的優化

8.11、分區

分區本身就是hive的一種優化

8.12、job的數量

一般是一個查詢產生一個job,然後通常情況一個job、可以是一個子查詢、一個join、一個group by 、一個limit等一些操作。

1個job:
select
a.*
from t1 a
left join t1 b
on a.order_id = b.order_id
;

8.13 analyze

參考官網:https://cwiki.apache.org/confluence/display/Hive/StatsDev

Analyze,分析表(也稱爲計算統計信息)是一種內置的Hive操作,可以執行該操作來收集表上的元數據信息。這可以極大的改善表上的查詢時間,因爲它收集構成表中數據的行計數,文件計數和文件大小(字節),並在執行之前將其提供給查詢計劃程序。

已經存在表的Analyze語法:
ANALYZE TABLE [db_name.]tablename [PARTITION(partcol1[=val1], partcol2[=val2], ...)]  -- (Note: Fully support qualified table name since Hive 1.2.0, see HIVE-10007.)
  COMPUTE STATISTICS 
  [FOR COLUMNS]          -- (Note: Hive 0.10.0 and later.)
  [CACHE METADATA]       -- (Note: Hive 2.1.0 and later.)
  [NOSCAN];

例1(指定分區)、
ANALYZE table dw_employee_hive partition(bdp_day=20190701) COMPUTE STATISTICS;
收集表的bdp_day=20190701的這個分區下的所有列列相關信息。它是一個細粒度的分析語句。它收集指定的分區上的元數據,並將該信息存儲在Hive Metastore中已進行查詢優化。該信息包括每列,不同值的數量,NULL值的數量,列的平均大小,平均值或列中所有值的總和(如果類型爲數字)和值的百分數。

例2(指定所有列)、
ANALYZE table dw_employee_hive partition(bdp_day=20190701) COMPUTE STATISTICS FOR COLUMNS;
收集表的bdp_day=20190701的這個分區下的所有列相關信息。

例3(指定某列)、
ANALYZE table dw_employee_hive partition(bdp_day=20190701) COMPUTE STATISTICS FOR COLUMNS snum,dept;

例4、
ANALYZE TABLE dw_employee_hive partition(bdp_day=20190701) COMPUTE STATISTICS NOSCAN;
收集指定分區相關信息,然後不進行掃描。

測試分析後的結果。
例1、
DESCRIBE EXTENDED dw_employee_hive partition(bdp_day=20190701);

描述結果:
...parameters:{totalSize=10202043, numRows=33102, rawDataSize=430326, ...

例2、
desc formatted dw_employee_hive partition(bdp_day=20190701) name;

結果如下:

# col_name  data_type   min max num_nulls   distinct_count  avg_col_len max_col_len num_trues   num_falses  comment

name string 0 37199 4.0 4 from deserializer

注意:
對分區表的分析,一般都要指定分區,如對全表分析,則可以這樣使用partition(bdp_day).
優化後查詢結果可以參考:https://www.cnblogs.com/lunatic-cto/p/10988342.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章