1. 程式人生 > >Hive筆記整理

Hive筆記整理

Hive 檢視

1、檢視的特點:

①不支援物化檢視
②只能查詢,不能做載入資料操作 load data into
③檢視的建立,只是儲存一份元資料,查詢檢視時才執行對應的子查詢
④view定義中若包含了ORDER BY/LIMIT語句,當查詢檢視時也進行ORDER BY/LIMIT語句操作,view當中定義的優先順序更高
⑤view支援迭代檢視
⑥一旦建立成功,無法修改

2、為什麼建立檢視?

select a.name,b.age from table1 a join table2 b on(a.id=b.id) => view
如果後期經常執行這個查詢語句,每次都寫麻煩
可以將長的SQL(資料表)與檢視對應對映,每次查詢這個檢視就是執行了長的SQL語句

3、檢視操作

#建立檢視
CREATE VIEW  IF NOT EXISTS  view1 AS SELECT * FROM logtbl order by age;
#可以檢視已經建立的檢視
show tables
#刪除檢視
drop view view1 

建立檢視的時候不會啟動MR任務
select * from view1;
但是在查詢檢視的時候會啟動MR任務
檢視的建立,只是儲存一份元資料,查詢檢視時才執行對應的子查詢

Hive 索引

索引

優化查詢效能
若使用select * from table where age = 10;假設這個表的資料非常大,是有10個block組成
name查詢的效能會很低
提高效能?
索引1(age > 10) block1(100,200) block2(200,389)
索引2(age = 10) block1(101,220) block2(200,389)
這個索引就類似目錄

建立索引庫,用於存放索引

create index t2_index on table psnbucket_partition(age) 
as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild 
in table t2_index_table;

索引庫中只是儲存一些元資料,比如 對哪個欄位建立索引,對哪個表建立索引等

alter index t2_index on psnbucket_partition rebuild; 

這一步是真正的建立索引資訊,並且儲存到索引庫中,若資料庫有新增資料,也可以使用以上語句重建索引

檢視索引庫:

66 hdfs://zfg/user/hive_remote/warehouse/psnbucket_partition/height=188.0/000000_0 [0,30,60,90,120] 188.0
77 hdfs://zfg/user/hive_remote/warehouse/psnbucket_partition/height=188.0/000000_0 [8,38,68,98,128] 188.0
88 hdfs://zfg/user/hive_remote/warehouse/psnbucket_partition/height=188.0/000000_0 [19,49,79,109,139] 188.0
11 hdfs://zfg/user/hive_remote/warehouse/psnbucket_partition/height=189.0/000000_0 [0,48,96,144,192] 189.0
22 hdfs://zfg/user/hive_remote/warehouse/psnbucket_partition/height=189.0/000000_0 [9,57,105,153,201] 189.0
查詢索引:
show index on psnbucket_partition;

刪除索引
drop index t2_index on psnbucket_partition;
刪除索引的同時 索引庫也會被刪除

資料讀取規則

之前往hive中載入的資料都是比較規整的,欄位與欄位之間都是分割好的,每一個欄位都不是髒資料,並且每一個欄位都是有意義的
但是在真實場景中不見得這個盡人意
tomcat執行日誌
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] “GET /bg-upper.png HTTP/1.1” 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] “GET /bg-nav.png HTTP/1.1” 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] “GET /asf-logo.png HTTP/1.1” 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] “GET /bg-button.png HTTP/1.1” 304 -
192.168.57.4 - - [29/Feb/2016:18:14:35 +0800] “GET /bg-middle.png HTTP/1.1” 304 -
192.168.57.4 - - [29/Feb/2016:18:14:36 +0800] “GET / HTTP/1.1” 200 11217

 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;

load data local inpath “/root/lo” into table logtbl;
原始髒資料不會變,只是在讀的時候,將髒資料清理掉再顯示出來。

192.168.57.4 - - 123儲存到檔案loerr中,然後將檔案載入到上面已經建立好的表中
load data local inpath “/root/loerr” into table logtbl; 這一步沒問題,因為load就是將資料拷貝到工作目錄區中
查詢看一下select * from logtbl 讀不懂,因為根據正則表示式的模板來讀資料,都不懂

總結:

讀時檢查
不是寫時檢查

beeline

之前在操作hive的是,直接通過hive命令進入hive cli進行資料分析以及處理,這種方式既不安全有不規範
beeline是一個新興的cli客戶端 類似jdbc/odbc 可以解決一切的問題,並且還能夠很好的解耦合
hive client直接連線HDFS、yarn
beeline需要先與thriftserver連線,thriftserver能夠進行安全認證、可靠認證、提高客戶端的併發

beeline預設連結hiveserver2的時候,不需要使用者名稱 密碼,預設方式也是不安全,我們可以設定hiveserver2使用者名稱、密碼
設定使用者名稱、密碼的步驟:
在hive-site.xml中新增一下資訊:

hive.server2.authentication
CUSTOM

    <property>
            <name>hive.jdbc_passwd.auth.zhangsan</name>
            <value>123456789</value>
    </property>
    <property>
            <name>hive.server2.custom.authentication.class</name>
            <value>com.hoe.hive.authoriz.UserPasswdAuth</value>
    </property>
寫程式碼:
	package com.hoe.hive.authoriz;
	import javax.security.sasl.AuthenticationException;
	import org.apache.hadoop.conf.Configuration;
	import org.apache.hadoop.hive.conf.HiveConf;
	import org.apache.hive.service.auth.PasswdAuthenticationProvider;
	import org.slf4j.Logger;
	import org.slf4j.LoggerFactory;

	public class UserPasswdAuth implements PasswdAuthenticationProvider {
		Logger logger = LoggerFactory.getLogger(UserPasswdAuth.class);
		private static final String USER_PASSWD_AUTH_PREFIX = "hive.jdbc_passwd.auth.%s";
		private Configuration conf = null;
		@Override
		public void Authenticate(String userName, String passwd) throws AuthenticationException {
			logger.info("user: " + userName + " try login.");
			String passwdConf = getConf().get(String.format(USER_PASSWD_AUTH_PREFIX, userName));
			if (passwdConf == null) {
				String message = "沒有發現密碼 " + userName;
				logger.info(message);
				throw new AuthenticationException(message);
			}
			if (!passwd.equals(passwdConf)) {
				String message = "使用者名稱密碼不匹配 " + userName;
				throw new AuthenticationException(message);
			}
		}
		public Configuration getConf() {
			if (conf == null) {
				this.conf = new Configuration(new HiveConf());
			}
			return conf;
		}
		public void setConf(Configuration conf) {
			this.conf = conf;
		}
	}

第一種連結方式:./beeline -u jdbc:hive2://node01:10000/test -n zhangsan -p123456789
第二種連結方式:
./beeline
!connect jdbc:hive2://node01:10000/test
輸入使用者名稱
輸入密碼

JDBC連線操作

因為通過JDBC連結hive 也是連結hiveserver2服務,連結成功才能操作hive
所以JDBC連結的時候也是需要使用者名稱 密碼的

package com.hoe.hive.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ConnectHive {

	public static String driverName = "org.apache.hive.jdbc.HiveDriver";

	public static void main(String[] args) {

		try {
			Class.forName(driverName);
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		String url = "jdbc:hive2://node01:10000";
		String userName = "zhangsan";
		String passwd = "123456789";
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(url, userName, passwd);
			Statement statement = conn.createStatement();
			String sql = "select * from test.logtbl limit 10";
			ResultSet resultSet = statement.executeQuery(sql);
			while (resultSet.next()) {
				System.out.println(resultSet.getString(1) + "-" + resultSet.getString(2));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

Hive內建函式

使用hive實現wordcount

建立資料表

create table docs(line string);

建立結果表

create table wc(word string, totalword int);

載入資料

load data local inpath ‘/tmp/wc’ into table docs;

統計wordcount並且將資料插入到結果表中

from (select explode(split(line, ' ')) as word from docs) w 
insert into table wc 
 select word, count(1) as totalword 
 group by word 
 order by word;

查詢結果

select * from wc;

自定義UDF

add jar /opt/software/hive/hive-1.2.1/lib/FormatTimeUDF.jar;
CREATE TEMPORARY FUNCTION convertTime AS 'com.hoe.hive.userdefinedfunction.FormatTimeUDF';
select convertTime(time) from logtbl;
DROP TEMPORARY FUNCTION convertTime;

自定義UDAF

add jar /opt/software/hive/hive-1.2.1/lib/ReduceTimeByResponseNumUDAF.jar;
CREATE TEMPORARY FUNCTION rrd AS ‘com.hoe.hive.userdefinedfunction.ReduceTimeByResponseNumUDAF’;
select referer,rrd(host) from logtbl group by referer;
DROP TEMPORARY FUNCTION rrd;

自定義UDTF

add jar /opt/software/hive/hive-1.2.1/lib/UserGenericUDTF.jar;
CREATE TEMPORARY FUNCTION exp AS ‘com.hoe.hive.userdefinedfunction.UserGenericUDTF’;
select exp(line) from udtfc;

永久函式

將相應的jar包上傳到HDFS上
create function formatTime AS ‘com.hoe.hive.userdefinedfunction.FormatTimeUDF’ using jar ‘hdfs://zfg/test/FormatTimeUDF.jar’;
create function exp AS ‘com.hoe.hive.userdefinedfunction.UserGenericUDTF’ using jar ‘hdfs://zfg//test/UserGenericUDTF.jar’;
create function rrd AS ‘com.hoe.hive.userdefinedfunction.ReduceTimeByResponseNumUDAF’ using jar ‘hdfs://zfg//test/ReduceTimeByResponseNumUDAF.jar’;

Hive指令碼執行方式:

不在hive中執行
hive -e “sql語句”–>顯示結果後退出
hive -e > “目錄” 追加結果到目錄中
hive -S -e “” :進入hive的靜默模式,只顯示查詢結果,不顯示執行過程
hive -f file:執行HQL(符合98-03標準)指令碼
hive -i “HQL指令碼檔案目錄”:執行Hive互動Shell時候先執行指令碼中的HQL語句