其它語言通過HiveServer2訪問Hive

柯廣發表於2020-12-18

先解釋一下幾個名詞:

  • 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.jarMETA-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;
    }
}

相關文章