Impala 和 Presto 概述及JDBC

目錄

  • 一、Impala
    • 1.1 Overview
    • 1.2 數據類型
    • 1.3 其他
    • 1.4 Impala JDBC
      • 1.4.1 Pom
      • 1.4.2 Code
  • 二、Presto
    • 2.1 Overview
    • 2.2 Presto的基本概念
    • 2.3 其他
    • 2.3 Presto JDBC
      • 2.3.1 Pom
      • 2.3.2 Code

一、Impala

Maven項目編寫Impala JDBC,使用Scala語言編寫代碼,如果需要可以自行更改爲Java代碼。

Impala JDBC 2.0 及更高版本使用的默認端口爲 21050,Impala服務器通過此端口接收JDBC連接。確保此端口可用於網絡上其他主機通信,例如,防火牆軟件是否阻止此端口。如果客戶端想使用其他端口連接,請修改Impala 端口號 --hs2_port並重啓Impala。

1.1 Overview

Apache Impala是Apache Hadoop的開源原生分析數據庫。多數BI工具都支持Impala,Impala爲基於Hadoop上的BI提供了低延遲和高併發性分析查詢,即使在多租戶環境下,Impala也可以線性擴展。

對於Apache Hive用戶,Impala使用相同的元數據和ODBC驅動程序。與Hive一樣,Impala支持SQL,因此您不必擔心重新造輪子。安裝完畢後,在 impala-shell中同步元數據到Impala,執行命令: invalidate metadata; 即可開始使用。

Impala可以提高 Apache Hadoop上SQL查詢性能,同時保留了熟悉的用戶體驗。使用Impala,您可以實時查詢數據,無論是存儲在HDFS還是Apache HBase中 - 包括SELECT,JOIN和聚合函數。

爲了避免延遲,Impala繞過MapReduce,而是通過專門的分佈式查詢引擎直接訪問數據,這個引擎非常類似於商業並行RDBMS中的查詢引擎,The result is order-of-magnitude faster performance than Hive, depending on the type of query and configuration.
Impala

1.2 數據類型

類型 條件 範圍 描述 句法
ARRAY複雜類型 僅適用於2.3或更高版本。文件類型只能爲Parquet或ORC格式 可以表示任意數量的有序元素的複雜數據類型,元素可以是標量或者另一個複雜類型 column_name ARRAY < type >
BIGINT -9223372036854775808 至9223372036854775807。沒有UNSIGNED子類型。 8字節整數數據類型 column_name BIGINT
BOOLEAN TRUE或FALSE 表示單個true / false選擇 column_name BOOLEAN
CHAR 僅適用於2.0或更高版本。對於Impala,長度是必需的。CHAR和VARCHAR列中的 所有數據必須使用與UTF-8兼容的字符編碼。 最大長度爲255 固定長度的字符類型,必要時尾部用空格填充以達到指定的長度。如果值長於指定的長度,則Impala會截斷所有尾部字符。 column_name CHAR(length)
DATE DATE類型在Impala 3.3及更高版本中可用 0000-01-01至9999-12-31 使用DATE數據類型存儲日期值
DECIMAL 僅適用於3.0或更高版本。3.x版本與2.版本有區別,如果繼續使用老版本,可設置SET DECIMAL_V2=FALSE。 -10 ^ 38 +1到10 ^ 38 –1 固定尺和精度的數值數據類型 DECIMAL[(precision[, scale])]
DOUBLE 4.94065645841246544e-324 至 1.79769313486231570e+308 正數或負數 雙精度浮點數據類型 column_name DOUBLE
FLOAT 1.40129846432481707e-45至3.40282346638528860e+38 正數或負數 單精度浮點數據類型 column_name FLOAT
INT 如果整數值太大而無法用INT 表示,請改用 BIGINT -2147483648 至 2147483647 使用的4字節整數數據類型 column_name INT
MAP複雜類型 僅適用於2.3或更高版本。在後臺,該MAP類型的實現方式與該ARRAY類型類似 。Impala不會對KEY值施加任何唯一性約束 表示任意一組鍵值對的複雜數據類型,key部分是一個標量類型,value部分可以是標量或另一複雜類型 column_name MAP < primitive_type, type >
REAL DOUBLE數據類型 的別名 column_name REAL
SMALLINT 如果整數值太大而不能用SMALLINT表示,請改用 INT。 -32768 至 32767 ,沒有UNSIGNED子類型 使用的2字節整數數據類型 column_name SMALLINT
STRING 在32 KB或更少的字符串上運行的查詢將可靠地工作,並且不會造成嚴重的性能或內存問題 對STRING的大小和一行總大小的硬性限制是2 GB;STRING寫入Parquet文件時 限制爲1 GB。 字符串 column_name STRING
STRUCT複雜類型 僅適用於2.3或更高版本。只能在具有Parquet或ORC文件格式的表或分區中使用。具有此數據類型的列不能用作分區表中的分區鍵列。 任何複雜類型(包括任何嵌套類型的聲明)的列定義的最大長度爲4000個字符。 代表單個項目的多個字段。經常用作ARRAY 或MAP的VALUE部分的元素類型 column_name STRUCT < name : type [COMMENT 'comment_string'], ... >
TIMESTAMP 1400-01-01至9999-12-31 TIMESTAMP數據類型保存日期和時間的值。可以將其分解爲年,月,日,小時,分鐘和秒字段,但是由於沒有可用的時區信息,因此它不對應於任何特定的時間點。更多關於日期函數請查看 Time Functions column_name TIMESTAMP
TINYINT 如果整數值太大而無法用TINYINT表示,請改用SMALLINT -128 至127。沒有UNSIGNED子類型 使用的1字節整數數據類型 column_name TINYINT
VARCHAR 僅適用於2.0或更高版本 您可以指定的最大長度爲65535。 可變長度字符類型,在處理過程中必要時將其截斷以適合指定的長度。 column_name VARCHAR(max_length)
複雜類型 僅適用於2.3或更高版本 複雜類型(也稱爲嵌套類型)使您可以在單個行/列位置中表示多個數據值

1.3 其他

1.4 Impala JDBC

1.4.1 Pom

只列出重要部分

<!-- *** Scala *** -->
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.8</version>
        </dependency>
        <!-- scala-compiler -->
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-compiler</artifactId>
            <version>2.11.8</version>
        </dependency>
        <!-- scala-reflect -->
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-reflect</artifactId>
            <version>2.11.8</version>
        </dependency>

		<!-- https://mvnrepository.com/artifact/com.cloudera.impala/jdbc -->
        <dependency>
            <groupId>com.cloudera.impala</groupId>
            <artifactId>jdbc</artifactId>
            <version>2.5.31</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.hive/hive-service -->
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-service</artifactId>
            <version>1.1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.hive</groupId>
                    <artifactId>hive-exec</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
        <dependency>
            <groupId>org.apache.thrift</groupId>
            <artifactId>libthrift</artifactId>
            <version>0.12.0</version>
        </dependency>

1.4.2 Code

package yore

import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}

/**
  * Impala JDBC
  *
  * Created by yore on 2019/5/20 06:46
  */
object ImpalaJDBCClient {

  private[yore] val JDBC_DRIVER: String = "com.cloudera.impala.jdbc41.Driver"
  // 端口可以查看:Impala 配置項 hs2_port
  private[yore] val URL = "jdbc:impala://cdh3:21050/kudu_test"

  def main(args: Array[String]): Unit = {
    var conn: Connection = null
    var ps: PreparedStatement = null

    try{
      Class.forName(JDBC_DRIVER)
      conn = DriverManager.getConnection(URL)

      var sql = "show tables"
      sql = "select * from tag_5 limit 10"

      ps = conn.prepareStatement(sql)
      val result: ResultSet = ps.executeQuery()

      val start = System.currentTimeMillis()
      while (result.next()){
        for(pos <- 1 to result.getMetaData.getColumnCount){
          print(result.getObject(pos) + "\t")
        }
        println()
      }
      val end = System.currentTimeMillis()
      println("-"*26 + s" Impala\n\t共花費:${(end - start).toDouble/1000} 秒")
    }catch {
      case e: Exception => e.printStackTrace()
    }finally {
      if(ps != null) ps.close()
      if(conn != null) conn.close()
      println("-"*26)
    }
  }
}

二、Presto

2.1 Overview

Presto 是一個在 Facebook 主持下運營的開源項目。Presto是一種旨在使用分佈式查詢有效查詢大量數據的工具,Presto是專門爲大數據實時查詢計算呢而設計和開發的產品,其爲基於 Java 開發的,對使用者和開發者而言易於學習。
Presto有時被社區的許多成員稱爲數據庫,官方也強調 Presto 不是通用關係數據庫,它不是 MySQL,PostgreSQL 或 Oracle 等數據庫的替代品,Presto 不是爲處理在線事務處理(OLTP)而設計的。

如果您使用太字節或數PB的數據,您可能會使用與 Hadoop 和 HDFS 交互的工具。Presto 被設計爲使用 MapReduce 作業(如Hive或Pig)管道查詢 HDFS 的工具的替代方案,但 Presto不限於訪問HDFS。
Presto 可以並且已經擴展到可以在不同類型的數據源上運行,包括傳統的關係數據庫和其他數據源像 Cassandra。Presto旨在處理數據倉庫和分析:數據分析,聚合大量數據和生成報告。這些工作負載通常歸類爲在線分析處理(OLAP)。

2.2 Presto的基本概念

  1. Coordinator
    Presto coordinator 是負責解析語句、查詢計劃和管理 Presto Worker 節點的服務器。它是 Presto 安裝的“大腦”,也是客戶端連接以提交語句以供執行的節點。
    每個 Presto 安裝必須有一個 Presto Coordinator 和一個或多個 Presto Worker。出於開發或測試目的,可以將單個 Presto 實例配置作爲這兩個角色。
    協調器跟蹤每個 Worker 的活動並協調查詢的執行。Coordinator 創建一個涉及一系列階段的查詢的邏輯模型,然後將其轉換爲在 Presto 工作集羣上運行的一系列連接任務。
    Coordinator 使用 REST API 與 Worker 和客戶進行通信。

  2. Worker
    Presto worker 是 Presto 安裝中的負責執行任務和處理數據服務器。Worker 從連接器獲取數據並相互交換中間數據。Coordinator 負責從工人那裏獲取結果並將最終結果返回給客戶。
    當Presto工作進程啓動時,它會將自己通告給 Coordinator 中的發現服務器,這使 Presto Coordinator可以執行任務。
    Worker 使用 REST API 與其他 Worker 和 Presto Coordinator 進行通信。

  3. Connector
    Connector 將 Presto 適配到數據源,如Hive或關係數據庫。您可以將 Connector 視爲與數據庫驅動程序相同的方式。它是 Presto SPI 的一個實現,它允許 Presto 使用標準 API 與資源進行交互。
    Presto 包含幾個內置連接器:一個用於 JMX 的連接器 ,一個提供對內置系統表的訪問的系統連接器,一個Hive連接器和一個用於提供 TPC-H 基準數據的TPCH連接器。
    許多第三方開發人員都提供了連接器,以便 Presto 可以訪問各種數據源中的數據。每個 Catalog 都與特定 Connector 相關聯。如果檢查 Catalog 配置文件,您將看到每個都包含強制屬性 connector.name,
    Catalog 使用該屬性爲給定 catalog 創建 Connector。可以讓多個 Catalog 使用相同的 Connector 來訪問類似數據庫的兩個不同實例。例如,如果您有兩個Hive集羣,則可以在單個 Presto 集羣中配置兩個 Catalog,
    這兩個 Catalog 都使用 Hive Connector,允許您查詢來自兩個 Hive 集羣的數據(即使在同一SQL查詢中)。

  4. Catalog
    Presto Catalog 包含 Schemas,並通過 Connector 引用數據源。例如,您可以配置 JMX catalog 以通過 JMX Connector 提供對 JMX 信息的訪問。
    在 Presto 中運行 SQL 語句時,您將針對一個或多個 Catalog 運行它。Catalog 的其他示例包括用於連接到 Hive 數據源的 Hive 目錄。
    當在 Presto 中尋址一個表時,全限定的表名始終以 Catalog 爲根。例如,一個全限定的表名稱hive.test_data.test 將引用 Hive catalog中 test_data庫中 test表。
    Catalog 在存儲在 Presto 配置目錄中的屬性文件中定義。

  5. Schema
    Schema 是組織表的一種方式。Schema 和 Catalog 一起定義了一組可以查詢的表。使用 Presto 訪問 Hive 或 MySQL 等關係數據庫時,Schema 會轉換爲目標數據庫中的相同概念。
    其他類型的 Connector 可以選擇以對底層數據源有意義的方式將表組織成 Schema。

  6. Table
    表是一組無序行,它們被組織成具有類型的命名列。這與任何關係數據庫中的相同。從源數據到表的映射由 Connector 定義。

  7. Statement
    Presto 執行與 ANSI 兼容的 SQL 語句。當 Presto 文檔引用語句時,它指的是 ANSI SQL 標準中定義的語句,它由子句(Clauses),表達式(Expression)和斷言(Predicate)組成。
    Presto 爲什麼將語句(Statment)和查詢(Query)概念分開呢?這是必要的,因爲在 Presto 中,Statment 只是引用 SQL 語句的文本表示。執行語句時,Presto 會創建一個查詢以及一個查詢計劃,然後該查詢計劃將分佈在​​一系列 Presto Worker 進程中。

  8. Query
    當 Presto 解析語句時,它會將其轉換爲查詢並創建分佈式查詢計劃,然後將其實現爲在 Presto Worker 進程上運行的一系列互連階段。在 Presto 中檢索有關查詢的信息時,您會收到生成結果集以響應語句所涉及的每個組件的快照。
    語句和查詢之間的區別很簡單。語句可以被認爲是傳遞給 Presto 的 SQL 文本,而查詢是指爲實現該語句而實例化的配置和組件。查詢包含 stages, tasks, splits, connectors以及協同工作以生成結果的其他組件和數據源。

  9. Stage
    當 Presto 執行查詢時,它會通過將執行分解爲具有層級關係的多個 Stage。例如,如果 Presto 需要聚合存儲在 Hive 中的10億行的數據,則可以通過創建根 State 來聚合其他幾個階段的輸出,所有這些階段都旨在實現分佈式查詢計劃的不同部分。
    包含查詢的層級關係結構類似於樹。每個查詢都有一個根 Stage,負責聚合其他 Stage 的輸出。階段是 Coordinator 用於建模分佈式查詢計劃的 Stage,但階段本身不在 Presto Worker 進程上運行。

  10. Task
    如上一部分所述,Stage 爲分佈式查詢計劃的特定部分建模,但 Stage 本身不在 Presto Worker 進程上執行。要了解 Stage 的執行方式,您需要了解 Stage 是通過 Presto Worker 網絡分發的一系列任務來實現的。
    任務是 Presto 架構中的“work horse”,因爲分佈式查詢計劃被解構爲一系列 Stage,然後將這些 Stage 轉換爲任務,然後執行或處理 split。Presto 任務具有輸入和輸出,正如一個 Stage 可以通過一系列任務並行執行,任務與一系列驅動程序並行執行。

  11. Split
    任務對拆分進行操作,拆分是較大數據集的一部分。分佈式查詢計劃的最低級別的 Stage 通過 Connector 的拆分檢索數據,而分佈式查詢計劃的更高級別的中間階段從其他階段檢索數據。
    當 Presto 正在安排查詢時,Coordinator 將查詢 Connector 以獲取可用於表的所有拆分的列表。Coordinator 跟蹤哪些計算機正在運行哪些任務以及哪些任務正在處理哪些拆分。

  12. Driver
    任務包含一個或多個並行 Driver。Driver 對數據進行操作並組合運算符以生成輸出,然後由任務聚合,然後將其傳遞到另一個 Stage 中的另一個任務。
    Driver 是一系列操作符實例,或者您可以將 Driver 視爲內存中的一組物理運算符。它是 Presto 架構中最低級別的並行性。Driver 有一個輸入和一個輸出。

  13. Operator
    Operator消費、轉換和生成數據。例如,表掃描從 Connector 獲取數據並生成可由其他運算符使用的數據,並且過濾器運算符通過在輸入數據上應用來使用 Predicate 數據並生成子集。

  14. Exchange
    交換在 Presto 節點之間傳輸數據以用於查詢的不同階段。任務使用交換客戶端將數據生成到輸出緩衝區並使用其他任務中的數據。

2.3 其他

2.4 Presto JDBC

如果查看

2.4.1 Pom

    <dependencies>
        <!-- https://mvnrepository.com/artifact/io.prestosql/presto-jdbc -->
        <dependency>
            <groupId>io.prestosql</groupId>
            <artifactId>presto-jdbc</artifactId>
            <version>314</version>
        </dependency>
    </dependencies>

2.4.2 Code

package yore;

import io.prestosql.jdbc.PrestoConnection;

import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.ZoneId;
import java.util.Properties;
import java.util.TimeZone;

/**
 * JDBC訪問 Presto
 * @see <a href="https://prestodb.github.io/docs/current/installation/jdbc.html">JDBC Driver<a/><br/>
 *
 * Created by yore on 2019/5/8 13:10
 */
public class PrestoJDBCClient {

    static final String JDBC_DRIVER  = "io.prestosql.jdbc.PrestoDriver";
    static final String URL = "jdbc:presto://cdh6:8080/kudu/default";

    public static void main(String[] args) {
        // @see <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">List of tz database time zones</a>
        // 設置時區,這裏必須要設置  map.put("CTT", "Asia/Shanghai");
        TimeZone.setDefault(TimeZone.getTimeZone(ZoneId.SHORT_IDS.get("CTT")));

        Properties properties = new Properties();
        properties.setProperty("user", "presto-user");
        properties.setProperty("SSL", "false");

        PrestoConnection conn = null;
        PreparedStatement ps = null;

        try {
            Class.forName(JDBC_DRIVER);
            conn = (PrestoConnection)DriverManager.getConnection(URL, properties);

            String sql = "show tables";
            sql = "select * from tag_5 limit 10";

            ps = conn.prepareStatement(sql);
            ResultSet result = ps.executeQuery();

            long start = System.currentTimeMillis();
            while (result.next()){
                for(int pos=1; pos< result.getMetaData().getColumnCount(); pos++){
                    System.out.print(result.getObject(pos) + "\t");
                }
                System.out.println();
            }

            long end = System.currentTimeMillis();
            System.out.println("--------------------------Presto" );
            System.out.println("\\t共花費:" + (double) (end - start) /1000 + "秒");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("--------------------------" );
        }
    }
}



最後我的筆記

其他關於Presot的可以查看 我的另一篇博客

End

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