先解釋一下幾個名詞:
-
metadata :hive後設資料,即hive定義的表名,欄位名,型別,分割槽,使用者這些資料。一般儲存關係型書庫mysql中,在測試階段也可以用hive內建Derby資料庫。
-
metastore :hivestore服務端。主要提供將DDL,DML等語句轉換為MapReduce,提交到hdfs中。
-
hiveserver2:hive服務端。提供hive服務。客戶端可以通過beeline,jdbc(即用java程式碼連結)等多種方式連結到hive。
-
beeline:hive客戶端連結到hive的一個工具。可以理解成mysql的客戶端。如:navite cat 等。
其它語言訪問hive
主要是通過hiveserver2服務,HiveServer2(HS2)是一種能使客戶端執行Hive查詢的服務。HiveServer2可以支援對 HiveServer2 的嵌入式和遠端訪問,支援多客戶端併發和身份認證。旨在為開放API客戶端(如JDBC和ODBC)提供更好的支援。
會啟動一個hive服務端預設埠為:10000,可以通過beeline,jdbc,odbc的方式連結到hive。hiveserver2啟動的時候會先檢查有沒有配置hive.metastore.uris,如果沒有會先啟動一個metastore服務,然後在啟動hiveserver2。如果有配置hive.metastore.uris。會連線到遠端的metastore服務。這種方式是最常用的。部署在圖如下:
Python連線Hive
Python3
訪問hive需要安裝的依賴有:
- pip3 install thrift
- pip3 install PyHive
- pip3 install sasl
- pip3 install thrift_sasl
這裡有一個Python
訪問Hive
的工具類:
# -*- coding:utf-8 -*-
from pyhive import hive
class HiveClient(object):
"""docstring for HiveClient"""
def __init__(self, host='hadoop-master',port=10000,username='hadoop',password='hadoop',database='hadoop',auth='LDAP'):
"""
create connection to hive server2
"""
self.conn = hive.Connection(host=host,
port=port,
username=username,
password=password,
database=database,
auth=auth)
def query(self, sql):
"""
query
"""
with self.conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
def insert(self, sql):
"""
insert action
"""
with self.conn.cursor() as cursor:
cursor.execute(sql)
# self.conn.commit()
# self.conn.rollback()
def close(self):
"""
close connection
"""
self.conn.close()
使用的時候,只需要匯入,然後建立一個物件例項即可,傳入sql
呼叫query
方法完成查詢。
# 拿一個連線
hclient = hive.HiveClient()
# 執行查詢操作
...
# 關閉連線
hclient.close()
注意:在insert
插入方法中,我將self.conn.commit()
和self.conn.rollback()
即回滾註釋了,這是傳統關係型資料庫才有的事務操作,Hive
中是不支援的。
Java連線Hive
Java
作為大資料的基礎語言,連線hive自然是支援的很好的,這裡介紹通過jdbc和mybatis兩種方法連線hive。
1. Jdbc連線
java通過jdbc連線hiveserver,跟傳統的jdbc連線mysql方法一樣。
需要hive-jdbc依賴:
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-jdbc</artifactId>
<version>1.2.1</version>
</dependency>
程式碼跟連線mysql
套路一樣,都是使用的DriverManager.getConnection(url, username, password)
:
@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
public class HiveConfigModel {
private String url = "jdbc:hive2://localhost:10000";
private String username = "hadoop";
private String password = "hadoop";
}
@Test
public void test(){
// 初始化配置
HiveConfigModel hiveConfigModel = ConfigureContext.getInstance("hive-config.properties")
.addClass(HiveConfigModel.class)
.getModelProperties(HiveConfigModel.class);
try {
Connection conn = DriverManager.getConnection(hiveConfigModel.getUrl(),
hiveConfigModel.getUsername(), hiveConfigModel.getPassword());
String sql = "show tables";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
ResultSet rs = preparedStatement.executeQuery();
List<String> tables = new ArrayList<>();
while (rs.next()){
tables.add(rs.getString(1));
}
System.out.println(tables);
} catch (SQLException e) {
e.printStackTrace();
}
}
在hive-jdbc-1.2.1.jar
的META-INF
下有個services
目錄,裡面有個java.sql.Driver
檔案,內容是:
org.apache.hive.jdbc.HiveDriver
java.sql.DriverManager
使用spi實現了服務介面與服務實現分離以達到解耦,在這裡jdbc
的實現org.apache.hive.jdbc.HiveDriver
根據java.sql.Driver
提供的統一規範實現邏輯。客戶端使用jdbc時不需要去改變程式碼,直接引入不同的spi介面服務即可。
DriverManager.getConnection(url, username, password)
這樣即可拿到連線,前提是具體實現需要遵循相應的spi規範。
2. 整合mybatis
通常都會使用mybatis
來做dao
層訪問資料庫,訪問hive
也是類似的。
配置檔案sqlConfig.xml
:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="production">
<environment id="production">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.apache.hive.jdbc.HiveDriver"/>
<property name="url" value="jdbc:hive2://master:10000/default"/>
<property name="username" value="hadoop"/>
<property name="password" value="hadoop"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/hive/test/test.xml"/>
</mappers>
</configuration>
mapper程式碼省略,實現程式碼:
public classTestMapperImpl implements TestMapper {
private static SqlSessionFactory sqlSessionFactory = HiveSqlSessionFactory.getInstance().getSqlSessionFactory();
@Override
public int getTestCount(String dateTime) {
SqlSession sqlSession = sqlSessionFactory.openSession();
TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
int count = testMapper.getTestCount(dateTime);
sqlSession.close();
return count;
}
}