大數據的分佈式SQL查詢引擎 -- Presto的詳細使用

Presto – Distributed SQL Query Engine for Big Data

官網 項目源碼 官方文檔

目錄




1 Presto 概述

Presto 是一個在 Facebook 主持下運營的開源項目(2012年秋啓動,2013年冬開源)。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.1 服務進程

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

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

2.2 數據源

(1). 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查詢中)。

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

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

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

2.3 查詢執行模型

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

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

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

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

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

(6). Driver
Task包含一個或多個並行 Driver。Driver 對數據進行操作並組合運算符以產生輸出,然後將輸出交由一個Task聚合,然後在另一個 Stage 中傳遞給另外一個Task。 Driver 是一系列操作符實例,或者您可以將 Driver 視爲內存中的一組物理運算符。它是 Presto 架構中最低級別的並行度。Driver 具有一個輸入和一個輸出。

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

(8). Exchange
Presto 的Stage通過Exchange來連接另一個Stage,Exchange用於完成有上下游關係的Stage之間的數據交換。Task將數據產生到輸出緩衝區中,並使用Exchange客戶端消費其它Task的數據。

3 整體架構

從前面的概念部分我們知道Presto中有兩類進程:Coordinator和Worker,在一個Presto集羣中是由一個Coordinator和多個Worker進程服務組成的。Coordinator負責接收(admitting)、解析(parsing)、計劃(planning)、優化查詢(optimizing queries)、查詢編排(query orchestration),Worker節點負責查詢處理,這是一個典型的Master-Slave的拓撲結構。
在這裏插入圖片描述

  • 客戶端通過HTTP協議發送一個包含SQL語句的HTTP請求給Presto 集羣的Coordinator;
  • Coordinator通過Discovery Service 發現當前集羣可用的Worker;
  • Coordinator將客戶端發送過來的查詢語句進行解析,生成查詢計劃,並根據查詢計劃執行計劃,依次生成SqlQueryExecution、SqlStageExecution、HttpRemoteTask, HttpRemoteTask是根據數據本地性生成的;
  • Coordinator將每一個Task部分發到其所需要處理的數據所在的Worker上進行執行。這個過程是通過HttpRemoteTask中的HttpClient將創建或者更新Task的請求發送給數據所在的節點上TaskResource所提供的RestFul接口,TaskResource接收到請求之後最終會在對應的Worker上啓動一個SqlTaskExecution對象或者更新應用的SqlTaskExecution對象需要處理的Split;
  • 執行處於上游的Source Stage中的Task,這些Task通過各種Connector從相應的數據源中讀取需要的數據;
  • 處於下游Stage中的Task會讀取上游Stage產生的輸出結果,並在改Stage每個Task所在的Worker的內存中運行後續的計算和處理;
  • Coordinator從分發Task之後,就會一直持續不斷地從Single Stage中的Task獲取計算結果,並將計算結果緩存到Buffer中,一直到所有的計算結束;
  • Client從提交查詢語句之後,就會不停地從Coordinator中獲取本次查詢的計算結果,直到獲取了所有的計算結果。並不知道等到所有的查詢結果都產生完畢之後一次全部顯示出來,而是每產生一部分,就會顯示一部分,直到所有的查詢結果都顯示完畢。
    在這裏插入圖片描述

4 Presto 安裝

可參考官方文檔:2.1. Deploying Presto

4.1 條件

安裝前準備:

  • 保證集羣各節點已經建立了 SSH 信任
  • 安裝 Java (JDK 1.8以上)
  • 主節點:
    • Git: 可以訪問 https://mirrors.edge.kernel.org/pub/software/scm/git/ 下載安裝。
    • Maven
  • 必要的數據源庫:例如 Mysql、Postgresql、Elasticsearch、Redis、MongoDB、Hive、Kafka、Kudu、Cassandra 等

4.2 安裝包的獲取

可以直接下載官網提供編譯好的包進行安裝 presto-server-0.190.tar.gz

本次以編譯源碼的方式獲取需要安裝的文件:
以源碼編譯方式安裝,訪問 presto-releases,現在需要的版本的源碼包。
通過下載release版源碼包編譯會出現問題,原因是這種方式缺少 .git目錄和文件

[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:19 min (Wall Clock)
[INFO] Finished at: 2019-05-12T02:57:56+08:00
[INFO] ------------------------------------------------------------------------
Downloaded from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/io/airlift/units/1.3/units-1.3.jar (18 kB at 129 kB/s)
Downloading from nexus-aliyun: http://maven.aliyun.com/nexus/content/groups/public/org/apache/commons/commons-lang3/3.4/commons-lang3-3.4.jar
[ERROR] Failed to execute goal pl.project13.maven:git-commit-id-plugin:2.1.13:revision (default) on project presto-matching: .git directory could not be found! Please specify a valid [dotGitDirectory] in your pom.xml -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :presto-matching
[root@cdh6 presto-0.219]#

問題解決。原因很簡單,就是下載的release源碼包中每個.git文件夾,但是git-commit-id-plugin插件又是需要這個目錄的,我們在父模塊的pom.xml中卻並沒有發現引用這個插件,其實這是airbase中依賴了git-commit-id-plugin插件,因此在父模塊的pom.xml文件中引入如下插件,並跳過此插件的配置的,大概在1335行左右,在<pluginManagement>標籤中的<plugins>中添加就行。

<plugin>
	<groupId>pl.project13.maven</groupId>
	<artifactId>git-commit-id-plugin</artifactId>
	<configuration>
	<skip>true</skip>
	</configuration>
</plugin>

如果不想改動源碼,可以直接 clone 源碼方式安裝,這種方式可以切換標籤,編譯官方發佈的任意我們需要的版本。

git clone https://github.com/prestodb/presto.git
git tag
# 可以看到不同的版本,找到最新的 0.219
git checkout tags/0.219
# 可以看到已經切換到此分支了
git branch

# 編譯
mvn -T2C install -DskipTests

等待一段時間後,顯示如下內容則表示編譯成功

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for presto-root 0.219:
[INFO]
[INFO] presto-root ........................................ SUCCESS [ 11.575 s]
[INFO] presto-spi ......................................... SUCCESS [ 30.813 s]
[INFO] presto-plugin-toolkit .............................. SUCCESS [  3.953 s]
[INFO] presto-client ...................................... SUCCESS [  8.612 s]
[INFO] presto-parser ...................................... SUCCESS [ 29.083 s]
[INFO] presto-geospatial-toolkit .......................... SUCCESS [ 28.109 s]
[INFO] presto-array ....................................... SUCCESS [  2.433 s]
[INFO] presto-matching .................................... SUCCESS [ 24.025 s]
[INFO] presto-memory-context .............................. SUCCESS [ 24.019 s]
[INFO] presto-tpch ........................................ SUCCESS [  9.667 s]
[INFO] presto-main ........................................ SUCCESS [01:36 min]
[INFO] presto-resource-group-managers ..................... SUCCESS [ 42.605 s]
[INFO] presto-tests ....................................... SUCCESS [ 23.371 s]
[INFO] presto-atop ........................................ SUCCESS [01:03 min]
[INFO] presto-jmx ......................................... SUCCESS [01:03 min]
[INFO] presto-record-decoder .............................. SUCCESS [ 33.159 s]
[INFO] presto-kafka ....................................... SUCCESS [01:13 min]
[INFO] presto-redis ....................................... SUCCESS [01:03 min]
[INFO] presto-accumulo .................................... SUCCESS [01:13 min]
[INFO] presto-cassandra ................................... SUCCESS [01:13 min]
[INFO] presto-blackhole ................................... SUCCESS [01:02 min]
[INFO] presto-memory ...................................... SUCCESS [01:02 min]
[INFO] presto-orc ......................................... SUCCESS [01:03 min]
[INFO] presto-benchmark ................................... SUCCESS [ 14.930 s]
[INFO] presto-parquet ..................................... SUCCESS [  5.787 s]
[INFO] presto-rcfile ...................................... SUCCESS [ 42.634 s]
[INFO] presto-hive ........................................ SUCCESS [ 21.288 s]
[INFO] presto-hive-hadoop2 ................................ SUCCESS [  8.084 s]
[INFO] presto-teradata-functions .......................... SUCCESS [ 47.924 s]
[INFO] presto-example-http ................................ SUCCESS [ 33.494 s]
[INFO] presto-local-file .................................. SUCCESS [ 33.505 s]
[INFO] presto-tpcds ....................................... SUCCESS [01:03 min]
[INFO] presto-raptor ...................................... SUCCESS [ 12.072 s]
[INFO] presto-base-jdbc ................................... SUCCESS [  4.513 s]
[INFO] presto-mysql ....................................... SUCCESS [ 25.919 s]
[INFO] presto-postgresql .................................. SUCCESS [ 15.107 s]
[INFO] presto-redshift .................................... SUCCESS [ 15.102 s]
[INFO] presto-sqlserver ................................... SUCCESS [ 15.086 s]
[INFO] presto-mongodb ..................................... SUCCESS [01:02 min]
[INFO] presto-ml .......................................... SUCCESS [01:02 min]
[INFO] presto-geospatial .................................. SUCCESS [  5.922 s]
[INFO] presto-jdbc ........................................ SUCCESS [ 22.349 s]
[INFO] presto-cli ......................................... SUCCESS [  9.009 s]
[INFO] presto-product-tests ............................... SUCCESS [01:04 min]
[INFO] presto-benchmark-driver ............................ SUCCESS [ 10.863 s]
[INFO] presto-password-authenticators ..................... SUCCESS [ 10.366 s]
[INFO] presto-session-property-managers ................... SUCCESS [ 10.463 s]
[INFO] presto-kudu ........................................ SUCCESS [01:13 min]
[INFO] presto-thrift-connector-api ........................ SUCCESS [ 34.061 s]
[INFO] presto-thrift-testing-server ....................... SUCCESS [01:21 min]
[INFO] presto-thrift-connector ............................ SUCCESS [  3.641 s]
[INFO] presto-elasticsearch ............................... SUCCESS [01:09 min]
[INFO] presto-server ...................................... SUCCESS [ 53.982 s]
[INFO] presto-server-rpm .................................. SUCCESS [01:08 min]
[INFO] presto-docs ........................................ SUCCESS [01:54 min]
[INFO] presto-verifier .................................... SUCCESS [ 31.352 s]
[INFO] presto-testing-server-launcher ..................... SUCCESS [ 25.514 s]
[INFO] presto-benchto-benchmarks .......................... SUCCESS [ 42.340 s]
[INFO] presto-proxy ....................................... SUCCESS [  6.275 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  07:32 min (Wall Clock)
[INFO] Finished at: 2019-05-11T13:40:14+08:00
[INFO] ------------------------------------------------------------------------

presto 目錄下 presto/presto-server/target 可看到剛編譯好的 presto-server-0.219.tar.gz,後續會使用這個包部署 Presto 集羣。

4.3 規劃

Presto 集羣部署分爲三個部分:

  • ①Presto Server端部署;
  • ②Presto Worker端部署;
  • ③Presto Client端部署

Presto集羣的規劃如下,這裏以3個節點爲例。

Host名 Coordinator Worker
cdh1 ✔️
cdh2 ✔️ ✔️
cdh3 ✔️

4.4 Presto Server部署

我們編譯後的presto-0.219/presto-server/target目錄下可以看到presto-server-0.219.tar.gz,我們使用這個包來部署,如果沒有編譯,也可以官方編譯好的Presto Server包presto-server-0.226.tar.gz來部署,這個包大概有577MB,推薦使用編譯方式獲取。

我們首先需要將presto-server-0.219.tar.gz包發送到一個服務節點(這裏是cdh2節點)的 /opt/presto-0.219目錄下,然後解壓,執行如下命令。

cd /opt/presto-0.219
# 解壓
tar -zxvf presto-server-0.219.tar.gz

# 進到解壓的目錄下
cd presto-server-0.219
# 查看文件,可以看到:bin  lib  NOTICE  plugin  README.txt。
# 在這裏可以看到並沒有配置文件的地方,這個需要自己手動創建Presto的配置文件的文件夾
ls

# 配置文件我們可以拷貝一份源碼中的,在下載的Presto源碼的根目錄下執行如下命令
scp -r presto-main/etc root@cdh2:/opt/presto-0.219/presto-server-0.219
scp presto-server-rpm/src/main/resources/dist/config/node.properties root@cdh2:/opt/presto-0.219/presto-server-0.219/etc

# 務必刪除一些我們不需要的配置文件(否則啓動時會加載監測配置文件)
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/blackhole.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/example.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/localfile.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/postgresql.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/raptor.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/sqlserver.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/tpcds.properties
rm -rf /opt/presto-0.219/presto-server-0.219/etc/catalog/tpch.properties

# 此時的presto-server-0.219目錄結構如下
├───────┬  presto-server-0.219
[文件夾] │ ├── bin
[文件夾] │ ├─┬ etc
[文件夾] │ │ ├─┬ catalog
[文件名] │ │ │ ├── hive.properties
[文件名] │ │ │ ├── jmx.properties
[文件名] │ │ │ ├── kafka.properties    	# 後面進行配置
[文件名] │ │ │ ├── kudu.properties
[文件名] │ │ │ ├── memory.properties
[文件名] │ │ │ ├── mongodb.properties
[文件名] │ │ │ └── mysql.properties
[文件夾] │ │ ├── kafka
[文件名] │ │ ├── config.properties
[文件名] │ │ ├── jvm.config
[文件名] │ │ ├── log.properties
[文件名] │ │ └── node.properties    		# 包含特定於每個節點的配置
[文件夾] │ ├── lib
[文件名] │ ├── NOTICE
[文件夾] │ ├── plugin
[文件名] │ └── README.txt

4.4.1 修改 node.properties 配置文件

進行如下配置,注意路徑。

node.environment=test
node.id=db519624-18e8-4ee5-af30-a6545d10fcdb
node.data-dir=/opt/presto/data
catalog.config-dir=/opt/presto-server-0.219/etc/catalog
plugin.dir=/opt/presto-server-0.219/plugin
node.server-log-file=/var/log/presto/server.log
node.launcher-log-file=/var/log/presto/launcher.log

node.environment: Presto運行環境名稱。屬於同一個Prosto集羣的節點必須有相同的環境名稱。
node.id: Presto集羣中的每個node的唯一標識。屬於同一個Presto集羣的各個Presto的node節點標識必須不同,可以以uuid的值指定屬於該屬性的值,linux可以用uuidgen生成。
node.data-dir: 在每個Presto Node所在服務器的操作系統中的路徑,Presto會在該路徑下存放日誌和其他的Presto數據。
catalog.config-dir :Presto 的Catalog的路徑,這裏我們把它配置到Presto配置文件目錄下。

4.4.2 修改 config.properties 配置文件

該配置文件的配置項應用於每個Presto的服務進程,每個Presto服務進程既可作爲Conrdinator,也可作爲Worker。

# Conrdinator & Wroker
coordinator=true
# 這個節點即爲Coordinator,又爲Worker
node-scheduler.include-coordinator=true
http-server.http.port=8080
query.max-memory=3GB
query.max-memory-per-node=2GB
query.max-total-memory-per-node=2GB
discovery-server.enabled=true
discovery.uri=http://cdh26:8080

exchange.http-client.connect-timeout=1m
exchange.http-client.idle-timeout=1m
exchange.http-client.max-connections=1000
exchange.http-client.max-connections-per-server=1000
#scheduler.http-client.max-connections=1000
#scheduler.http-client.max-connections-per-server=1000
#scheduler.http-client.connect-timeout=1m
#scheduler.http-client.idle-timeout=1m
query.client.timeout=5m
query.min-expire-age=30m
presto.version=presto-0.219
## You may also wish to set the following properties:
# Specifies the port for the JMX RMI registry. JMX clients should connect to this port.
#jmx.rmiregistry.port: 
# Specifies the port for the JMX RMI server. Presto exports many metrics that are useful for monitoring via JMX.
#jmx.rmiserver.port: 

distributed-index-joins-enabled=true
exchange.client-threads=8
optimizer.optimize-hash-generation=true
query.hash-partition-count=2

coordinator: Presto集羣中的當前節點是否作爲Coordinator,即當前節點可以接受來自客戶端的查詢請求,並且管理查詢的執行過程。
node-scheduler.include-coordinator: 是否允許在Coordinator上執行計算任務,若允許計算計算任務,則Coordinator節點除了接受客戶端的查詢請求、管理查詢的執行過程,還需要執行普通的計算任務。
http-server.http.port: 指定HTTP Server的端口號,Presot通過HTTP協議進行所有的內部和外部通信。
query.max-memory: 一個單獨的計算任務使用的最大內存數。內存的大小直接限制了可以運行Order By 計算的行數。該配置應該基於查詢複雜度、查詢的數據量,以及查詢的併發數進行設置。
query.max-memory-per-node: 查詢可在任何一臺計算機上使用的最大用戶內存量。
query.max-total-memory-per-node: 查詢可在任何一臺計算機上使用的最大用戶和系統內存量,其中系統內存是讀取器、寫入程序和網絡緩衝區等執行期間使用的內存。
discovery-server.enabled: Presto使用Discover服務來查找集羣中的所有節點,每個Presto實例都會在啓動時使用Discovery服務註冊自己。爲了簡化部署可以在Coordinator節點啓動的時候啓動Discover服務。
discovery.uri: Discovery服務器的URI。因爲我們已經將Discovery嵌入了Presto Coordinator服務中,因此它應該是Presto Coordinator的URI。注意,改URI不要以/結尾。

4.4.3 修改 jvm.config 配置文件

Presto是Java語言開發的,每個Presto服務進程都是運行在JVM之上的,因此需要在配置文件中指定Presto服務進程的Java運行環境。改配置文件中包含了一系列啓動Java虛擬機時所需要的命令行參數。 在集羣中Coordinator和Worker上的JVM配置文件是一樣的。

#
# WARNING
# ^^^^^^^
# This configuration file is for development only and should NOT be used be
# used in production. For example configuration, see the Presto documentation.
#
-server
# 設置能夠使用的最大內存
-Xmx16G
-XX:+UseG1GC
-XX:+ExplicitGCInvokesConcurrent
-XX:+AggressiveOpts
-XX:+HeapDumpOnOutOfMemoryError
-XX:OnOutOfMemoryError=kill -9 %p
-XX:InitiatingHeapOccupancyPercent=75
-XX:MaxGCPauseMillis=600
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExitOnOutOfMemoryError

4.4.4 修改 log.properties 配置文件

在改配置文件中設置Logger的最小日誌級別。我這裏採用默認,如果要用於調試,可以改爲DEBUG等級。

com.facebook.presto=INFO
com.sun.jersey.guice.spi.container.GuiceComponentProviderFactory=WARN
com.ning.http.client=WARN
com.facebook.presto.server.PluginManager=DEBUG

4.4.5 修改 Catalog 配置文件

Presto通過 Connector 來訪問數據,一種類型的數據源與一種而類型的Connector對應。
在Presto實際使用過程中,會根據實際的業務需要建立一個或者多個Catalog,而每種Catalog都有一個特定類型的Connector與之對應。
更多的Connector可以訪問 Connectors

以先配置幾種常用的Connector ,根據自己使用Connector進行配置即可。

(1) MySQL

Mysql配置presto-server-0.219/etc/catalog/mysql.properties ,配置如下。MySQL Connector 官方文檔

connector.name=mysql
connection-url=jdbc:mysql://mysql:13306
connection-user=root
connection-password=swarm

(2) Hive

配置 Hive,修改 presto-server-0.219/etc/catalog/hive.properties 配置文件,如下配置。Hive Connector 官方文檔

connector.name=hive-hadoop2
# Hive Metastore 服務器端口 
hive.metastore.uri=thrift://cdh3:9083
hive.config.resources=/etc/hadoop/conf/core-site.xml,/etc/hadoop/conf/hdfs-site.xml,/etc/hadoop/conf/mapred-site.xml
# 是否允許在Presto中刪除Hive中的表
hive.allow-drop-table=true
# 是否允許在Presto中重命名Hive中的表
hive.allow-rename-table=true

(3) Kudu

Kudu Connector 官方文檔
修改 presto-server-0.219/etc/catalog/kudu.properties 配置文件,如下配置

connector.name=kudu

## List of Kudu master addresses, at least one is needed (comma separated)
## Supported formats: example.com, example.com:7051, 192.0.2.1, 192.0.2.1:7051,
##                    [2001:db8::1], [2001:db8::1]:7051, 2001:db8::1
kudu.client.master-addresses=cdh3:7051

## Kudu does not support schemas, but the connector can emulate them optionally.
## By default, this feature is disabled, and all tables belong to the default schema.
## For more details see connector documentation.
#kudu.schema-emulation.enabled=false

## Prefix to use for schema emulation (only relevant if `kudu.schema-emulation.enabled=true`)
## The standard prefix is `presto::`. Empty prefix is also supported.
## For more details see connector documentation.
#kudu.schema-emulation.prefix=

#######################
### Advanced Kudu Java client configuration
#######################

## Default timeout used for administrative operations (e.g. createTable, deleteTable, etc.)
kudu.client.default-admin-operation-timeout = 30s

## Default timeout used for user operations
kudu.client.default-operation-timeout = 30s

## Default timeout to use when waiting on data from a socket
kudu.client.default-socket-read-timeout = 10s

## Disable Kudu client's collection of statistics.
#kudu.client.disable-statistics = false

(4) MongoDB

MongoDB Connector官方文檔
MongoDB版本官方強烈建議使用3.0或者更高版本,但也支持2.6+版本。

修改 presto-server-0.219/etc/catalog/mongodb.properties 配置文件,如下配置

connector.name=mongodb
## List of all mongod servers
mongodb.seeds=host:27017
## The maximum wait time
mongodb.max-wait-time=30

(5) Kafka

Kafka Connector官方文檔

連接器允許將Apache Kafka主題用作Presto中的表。每條消息在Presto中顯示爲一行。支持Apache Kafka 0.8+,但強烈建議使用0.8.1或更高版本。

etc/catalog/ 下新建配置文件kafka.properties,如下配置

connector.name=kafka
kafka.default-schema=default
kafka.table-names=canal,spin,spout
kafka.nodes=cdh1:9092,cdh2:9092,cdh3:9092
# d(天)、h(小時)、m(分鐘)、s(秒)、ms(毫秒)、us(微秒)、ns(納秒)、
kafka.connect-timeout=10s

4.4.6 Presto Worker 配置

將配置好的/opt/presto-0.219/presto-server-0.219發送到Presto其它節點(這裏是cdh1和cdh2)。

# scp發送到其它worker節點
scp -r /opt/presto-0.219/presto-server-0.219 root@cdh1:/opt/presto-0.219
scp -r /opt/presto-0.219/presto-server-0.219 root@cdh3:/opt/presto-0.219

然後修改各個Worker節點的/opt/presto-0.219/presto-server-0.219/etc/config.properties配置文件,使其只作爲Worker節點。

# Conrdinator & Worker
coordinator=false
#node-scheduler.include-coordinator=true
http-server.http.port=8080
# 下面的內存配置的越大越好。
query.max-memory=3GB
query.max-memory-per-node=1GB
query.max-total-memory-per-node=2GB
#discovery-server.enabled=true
discovery.uri=http://cdh2:8080

修改各個Worker節點的/opt/presto-0.219/presto-server-0.219/etc/node.properties配置文件,使得每個節點的node.id不一樣,可以在linux系統下使用uuidgen生成一個。

[root@cdh3 ~]# uuidgen
e0bb6be6-b35a-4a04-8967-93ad4f632a46
[root@cdh3 ~]# vim /opt/presto-0.219/presto-server-0.219/etc/node.properties

# 將node.id修改爲剛生成的uuid
node.id=e0bb6be6-b35a-4a04-8967-93ad4f632a46

# 其它節點同樣方式修改即可,例如cdh1節點

4.4.7 Presto服務的啓停

到每個節點,通過運行以下命令將Presto作爲守護程序啓動:

# 啓動Presto服務
/opt/presto-0.219/presto-server-0.219/bin/launcher start
Started as 30065

#查看Presto服務運行狀態
/opt/presto-0.219/presto-server-0.219/bin/launcher status

#查看Java進程。會看到 PrestoServer 進程
[root@cdh2 presto-server-0.219]# jps

#一起啓動其它Worker節點的服務

#停止Presto。關閉每個節點
/opt/presto-0.219/presto-server-0.219/bin/launcher stop

查看日誌,進入到node.properties配置的node.data-dir目錄下(/opt/presto-0.219/data/var/log)找到server.log查看日誌,如下日誌信息表示啓動成功。

2019-05-18T21:41:04.405+0800    INFO    main    com.facebook.presto.security.AccessControlManager       -- Loaded system access control allow-all --
2019-05-18T21:41:04.503+0800    INFO    main    com.facebook.presto.server.PrestoServer ======== SERVER STARTED ========

4.5 Presto Client部署

到這一步我們的Presto已經安裝成功,但是我們現在還沒有一個客戶端,暫時沒法將SQL提交到Presto集羣執行,因此我們爲了更加方便的使用,還得安裝一個Presto Client。這個安裝比較簡單,直接獲取一個presto-cli-0.219-executable.jar包即可。

這裏又兩種方式,第一種直接下載官方編譯好的客戶端執行工具包 presto-cli-0.219-executable.jar,這個包大概有13.8MB。第二種方法直接將我們編譯成功的包發送到Presto的任一節點即可(如果在每個節點都可執行,那麼就每個節點都放一份),複製presto-0.219/presto-cli/target/presto-cli-0.219-executable.jar

# scp到cdh2節點
scp presto-0.219/presto-cli/target/presto-cli-0.219-executable.jar root@cdh2:/opt/presto-0.219

# 進入到cdh2節點
# 重命名presto-cli-0.219-executable.jar 包爲presto
mv /opt/presto-0.219/presto-cli-0.219-executable.jar /opt/presto-0.219/presto
# 賦予執行的權限
chmod +x /opt/presto-0.219/presto

# 爲了方便使用,可以將其配置到環境變量中。注意一定是 >> ,單個會清除原有內容再添加
echo "export PATH=$PATH:/opt/presto-0.226/">>/etc/profile
source /etc/profile

# 測試,獲取presto-cli 的幫助信息
presto --help



5 網頁客戶端工具

Airpal是來自於Airbnb(愛彼迎)的一個基於Web的查詢工具,它建立在Facebook的PrestoDB(Presto)之上,它提供了查找表、查看元數據、瀏覽抽樣行、編寫和編輯查詢,然後在Web見面中提交查詢的功能。查詢運行後,用戶可以跟蹤查詢進度,完成後,可以通過瀏覽器以CSV格式返回結果。查詢結果可用於生成新的Hive表已進行後續分析,並且Airpal維護該工具中運行的所有查詢的可搜索歷史記錄。

因爲這個項目許久未更新,編譯和使用的時候回出現許多問題,基本無法使用,所以這個不推薦使用,如果想嘗試安裝的,可以參考網上的博客 Airpal安裝部署 自己構建和安裝。這裏我們推薦使用yanagishima,它是適用於Presto和Hive的Web UI,而且後很多的特性,是一個相對比較好用的Web工具。因爲yanagishima是Gradle構建的項目,因此我們需要辦證環境中已經安裝配置了Gradle。

5.1 Gradle安裝

在前面編譯的那個機器(安裝有Maven的)上安裝Gradle。

# 下載Gradle
wget http://services.gradle.org/distributions/gradle-5.6.2-bin.zip 
mv gradle-5.6.2-bin.zip /usr/local

# 解壓
unzip /usr/local/gradle-5.6.2-bin.zip
mv /usr/local/gradle-5.6.2 /usr/local/gradle

# 配置到環境變量。將下面的兩行插入到 /etc/profile。記得:source /etc/profile
export GRADLE_HOME=/usr/local/gradle
export PATH=$PATH:$GRADLE_HOME/bin

# 查看是否生效
gradle -v

5.2 Node.js安裝

# 1下載Node.js包
wget https://nodejs.org/dist/v10.16.3/node-v10.16.3-linux-x64.tar.xz

# 2 解壓
tar -xf node-v10.16.3-linux-x64.tar.xz -C /usr/local
# 3 重命名
mv /usr/local/node-v10.16.3-linux-x64 /usr/local/nodejs

# 4 修改屬組
chown -R root:root /usr/local/nodejs

# 5 執行node命令,查看版本
/usr/local/nodejs/bin/node -v

# 6 創建軟連接
ln -s /usr/local/nodejs/bin/node /usr/local/bin
ln -s /usr/local/nodejs/bin/npm  /usr/local/bin

# 7 安裝node-sass。Install from mirror in China。
# 詳細說明訪問:https://github.com/sass/node-sass#install-from-mirror-in-china
# 注意:如果報文件權限不夠,就賦予 774 權限。如果沒有文件就手動創建。
npm install -g mirror-config-china --registry=http://registry.npm.taobao.org
npm install node-sass

5.3 下載源碼並編譯

# 1克隆 yanagishima
git clone https://github.com/yanagishima/yanagishima.git
cd yanagishima/

# 2 編譯
# 2.1 查看當前的可供選擇的tag
git tag
# 2.2 切換到對應的分支上。這裏選擇20.0版本,因爲之後的對jdk要求是 Java 11,我們使用Java 8的來編譯
git checkout -b 20.0 refs/tags/20.0
# 2.3 查看當前所在的分支
git branch
# 2.4 編譯打包。如果重新編譯,
# ./gradlew clean
./gradlew distZip
#……
#> Task :compileJava
#Note: Some input files use unchecked or unsafe operations.
#Note: Recompile with -Xlint:unchecked for details.
#BUILD SUCCESSFUL in 7m 30s
#11 actionable tasks: 11 executed

# 3 將編譯好的包發送的安裝節點
scp  build/distributions/yanagishima-20.0.zip root@node2:/opt/presto-0.219

# 4 到node2節點,解壓配置
cd /opt/presto-0.219/
unzip yanagishima-20.0.zip

5.4 修改yanagishima的配置文件

我們主要修改/opt/presto-0.219/yanagishima-20.0/conf/yanagishima.properties配置文件。爲了防止端口衝突(lsof -i:8080),可以修改爲其它端口號,這裏我修改爲 38080

# yanagishima web port
jetty.port=38080
# 30 minutes. If presto query exceeds this time, yanagishima cancel the query.
presto.query.max-run-time-seconds=1800
# 1GB. If presto query result file size exceeds this value, yanagishima cancel the query.
presto.max-result-file-byte-size=1073741824
# you can specify freely. But you need to specify same name to presto.coordinator.server.[...] and presto.redirect.server.[...] and catalog.[...] and schema.[...]
presto.datasources=my-presto
auth.my-presto=false
# presto coordinator url
presto.coordinator.server.my-presto=http://cdh2:8080
# almost same as presto coordinator url. If you use reverse proxy, specify it
presto.redirect.server.my-presto=http://cdh2:8080
# presto catalog name
catalog.my-presto=hive
# presto schema name
schema.my-presto=default
# if query result exceeds this limit, to show rest of result is skipped
select.limit=500
# http header name for audit log
audit.http.header.name=some.auth.header
use.audit.http.header.name=false
# limit to convert from tsv to values query
to.values.query.limit=500
# authorization feature
check.datasource=false
hive.jdbc.url.your-hive=jdbc:hive2://cdh3:10000/default
hive.jdbc.user.your-hive=hive
hive.jdbc.password.your-hive=hive
hive.query.max-run-time-seconds=3600
hive.query.max-run-time-seconds.your-hive=3600
resource.manager.url.your-hive=http://cdh3:8088
sql.query.engines=presto,hive
hive.datasources=your-hive
hive.disallowed.keywords.your-hive=insert,drop
# 1GB. If hive query result file size exceeds this value, yanagishima cancel the query.
hive.max-result-file-byte-size=1073741824
# 注意一定要在這個目錄下新建一個空的hive_setup_query_your-hive文件
hive.setup.query.path.your-hive=/opt/presto-0.219/yanagishima-20.0/conf/hive_setup_query_your-hive
cors.enabled=false

5.5 yanagishima的啓停

# 啓動。注意:務必進入到yanagishima-20.0目錄下啓動,否則頁面會報 404 
cd /opt/presto-0.219/yanagishima-20.0/
nohup bin/yanagishima-start.sh >y.log 2>&1 &

# 停止
/opt/presto-0.219/yanagishima-20.0/bin/yanagishima-shutdown.sh

查看日誌,顯示如下表示啓動成功。

2019/05/20 15:51:26.515 +0800 INFO [YanagishimaServer] [Yanagishima] Loading yanagishima settings file from bin/../conf
2019/05/20 15:51:26.517 +0800 INFO [YanagishimaServer] [Yanagishima] Loading yanagishima properties file
2019/05/20 15:51:27.345 +0800 INFO [log] [Yanagishima] Logging initialized @2485ms
2019/05/20 15:51:27.430 +0800 INFO [YanagishimaServer] [Yanagishima] Yanagishima Server started...
2019/05/20 15:51:27.433 +0800 INFO [Server] [Yanagishima] jetty-9.3.7.v20160115
2019/05/20 15:51:27.753 +0800 INFO [ContextHandler] [Yanagishima] Started o.e.j.s.ServletContextHandler@65987993{/,file:///opt/presto-0.226/yanagishima-20.0/web/,AVAILABLE}
2019/05/20 15:51:27.779 +0800 [ServerConnector] [Yanagishima] Started ServerConnector@5b38c1ec{HTTP/1.1,[http/1.1]}{0.0.0.0:38080}
2019/05/20 15:51:27.779 +0800 INFO [Server] [Yanagishima] Started @2933ms
2019/05/20 15:51:27.780 +0800 INFO [YanagishimaServer] [Yanagishima] Yanagishima Server running port 38080.

5.6 yanagishima的使用

如果上一步啓動沒有問題,我們可以瀏覽器訪問:http://cdh2:38080 ,可以看到如下頁面,這個是Presto的頁面。
在這裏插入圖片描述

我們也可以只直接操作Hive,頁面如下。注意在寫SQL時一定不要加分號作爲結束。
在這裏插入圖片描述
我們現在Presto中執行如下SQL,結果如下圖所示。
在這裏插入圖片描述

我們同樣的方式通過頁面在Hive中直接執行上面的SQL,結果如下圖所示。

SELECT m.id,m.movie_name,m.rating_num,m.rating_people,q.rank,q.quote FROM movie m 
LEFT JOIN quote q ON q.id=m.id 
ORDER BY m.rating_num desc,m.rating_people desc limit 10

在這裏插入圖片描述
同時我們還可以看到這個SQL的執行計劃的信息,如下圖所示。
在這裏插入圖片描述


6 Presto 使用

6.1 Presto CLI

# Hive
presto --server cdh2:8080 --catalog hive --schema 庫名
# Mysql
presto --server cdh2:8080 --catalog mysql --schema 庫名
# Kafka
presto --server cdh2:8080 --catalog kafka --schema test
# Kudu
presto --server cdh2:8080 --catalog kudu --schema default
# MongoDB
presto --catalog mongodb --schema Mongo庫名

6.1.1 MySQL

我們先登錄MySQL,簡單的查看一下數據,可以看到2千萬條數據大概花了26.56秒。

-- 選擇庫
mysql> use flink_test;

-- count一下表vote_recordss_memory的數據條數
mysql>  SELECT count(*) FROM vote_recordss_memory;
+----------+
| count(*) |
+----------+
| 19999998 |
+----------+
1 row in set (26.56 sec)

接下來我們使用Presto,Catalog使用mysql,操作同一份數據看下執行情況。和MySQL的時間基本差不多,甚至稍快些,在多次查詢同一份數據(高併發)時Presto的時間會更快些。從這裏可以看到,Presto數據的獲取會花費一部分時間,數據的處理可以充分的發揮大數據的分佈式計算的優勢,進行快速數據分析。

# 1 登錄
[root@cdh2 ~]# presto  --server cdh2:8080 --catalog mysql --schema flink_test

# 2 查看庫下的表
presto:flink_test> show tables;
         Table
------------------------
# …… 已省去其它表
vote_recordss_memory
(18 rows)
Query 20191015_012019_00002_fxstp, FINISHED, 2 nodes
Splits: 36 total, 36 done (100.00%)
0:01 [18 rows, 547B] [12 rows/s, 378B/s]

# 3統計 vote_recordss_memory 表的數據。注意不要加反單引號。
presto:flink_test> SELECT count(*) FROM vote_recordss_memory;
  _col0
----------
 19999998
(1 row)
Query 20191015_012537_00007_fxstp, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:21 [20M rows, 0B] [952K rows/s, 0B/s]

6.1.2 Hive

在hvie中 default 庫下執行如下查詢

--獲取評分最高且評論人數最多的電影評語。order by 和 sort by
0: jdbc:hive2://node-a.test.com:10000> SELECT m.id,m.movie_name,m.rating_num,m.rating_people,q.rank,q.quote FROM movie m LEFT JOIN quote q ON q.id=m.id ORDER BY m.rating_num desc,m.rating_people desc limit 10;

+----------+------------------------------------------+---------------+------------------+---------+------------------+
|   m.id   |               m.movie_name               | m.rating_num  | m.rating_people  | q.rank  |     q.quote      |
+----------+------------------------------------------+---------------+------------------+---------+------------------+
| 1292052  | 肖申克的救贖 The Shawshank Redemption (1994)  | 9.7           | 1502851          | 1       | 希望讓人自由。          |
| 1291546  | 霸王別姬 (1993)                              | 9.6           | 1112641          | 2       | 風華絕代。            |
| 1296141  | 控方證人 Witness for the Prosecution (1957)  | 9.6           | 195362           | 29      | 比利·懷德滿分作品。       |
| 1292063  | 美麗人生 La vita è bella (1997)             | 9.5           | 690618           | 5       | 最美的謊言。           |
| 1295124  | 辛德勒的名單 Schindler's List (1993)        | 9.5           | 613865           | 8       | 拯救一個人,就是拯救整個世界。  |
| 1295644  | 這個殺手不太冷 Léon (1994)                    | 9.4           | 1363430          | 3       | 怪蜀黍和小蘿莉不得不說的故事。  |
| 1292720  | 阿甘正傳 Forrest Gump (1994)                 | 9.4           | 1178003          | 4       | 一部美國近現代史。        |
| 1292722  | 泰坦尼克號 Titanic (1997)                     | 9.4           | 1119405          | 7       | 失去的纔是永恆的。        |
| 1293182  | 十二怒漢 12 Angry Men (1957)                 | 9.4           | 253408           | 36      | 1957年的理想主義。      |
| 1291561  | 千與千尋 千と千尋の神隠し (2001)                | 9.3           | 1205228          | 6       | 最好的宮崎駿,最好的久石讓。   |
+----------+------------------------------------------+---------------+------------------+---------+------------------+
10 rows selected (40.425 seconds)

在Presto 執行同樣的查詢

-- 1 登錄
[root@cdh2 ~]# presto  --server cdh2:8080 --catalog hive --schema default

-- 2 查看可用的表
presto:default> SHOW TABLES;
             Table
-------------------------------
# …… 已省略其它未涉及到的表
 movie
 quote
 (6 rows)
Query 20191015_014031_00013_fxstp, FINISHED, 2 nodes
Splits: 36 total, 36 done (100.00%)
0:01 [6 rows, 173B] [7 rows/s, 226B/s]

-- 3 我們執行第二章實戰項目的查詢,這裏注意加上分號作爲結束
--  可以看到大概花了7秒鐘就統計出了結果,
presto:default> SELECT m.id,m.movie_name,m.rating_num,m.rating_people,q.rank,q.quote FROM movie m
             -> LEFT JOIN quote q ON q.id=m.id 
             -> ORDER BY m.rating_num DESC,m.rating_people DESC LIMIT 10;
   id    |                  movie_name                  | rating_num | rating_people | rank |             quote
---------+--------------------------------------------+------------+--------------+------+---------------------
 1292052 | 肖申克的救贖 The Shawshank Redemption (1994) |        9.7 |       1502851 |    1 | 希望讓人自由。
 1291546 | 霸王別姬 (1993)                              |        9.6 |       1112641 |    2 | 風華絕代。
 1296141 | 控方證人 Witness for the Prosecution (1957) |        9.6 |        195362 |   29 | 比利·懷德滿分作品。
 1292063 | 美麗人生 La vita è bella (1997)              |        9.5 |        690618 |    5 | 最美的謊言。
 1295124 | 辛德勒的名單 Schindler's List (1993)     |        9.5 |        613865 |    8 | 拯救一個人,就是拯救整個世界。
 1295644 | 這個殺手不太冷 Léon (1994)                 |        9.4 |       1363430 |    3 | 怪蜀黍和小蘿莉不得不說的故事。
 1292720 | 阿甘正傳 Forrest Gump (1994)              |        9.4 |       1178003 |    4 | 一部美國近現代史。
 1292722 | 泰坦尼克號 Titanic (1997)                  |        9.4 |       1119405 |    7 | 失去的纔是永恆的。
 1293182 | 十二怒漢 12 Angry Men (1957)               |        9.4 |        253408 |   36 | 1957年的理想主義。
 1291561 | 千與千尋 千と千尋の神隠し (2001)            |        9.3 |       1205228 |    6 | 最好的宮崎駿,最好的久石讓。
(10 rows)
Query 20191015_014345_00014_fxstp, FINISHED, 2 nodes
Splits: 115 total, 115 done (100.00%)
0:07 [500 rows, 176KB] [72 rows/s, 25.5KB/s]

6.1.3 Kudu

因爲Kudu表時通過Impala創建的,因此表名前面都帶有impala::前綴,並且也包含了庫名信息,在Presto執行是因爲英文冒號是特殊字符,只需要將庫名用引號引起來,在Presto就可以執行。從執行的效果來看也是很快,但是Presto的控制檯執行時間精確到的是秒,小於1秒的都顯示爲了0秒。

# 1 通過Presto連接Kudu
[root@cdh2 ~]# presto  --server cdh2:8080 --catalog kudu --schema default

-- 2 查看當前可用的表列表。可以看到我們通過Impala創建的Kudu表都加有 impala:: 前綴。
presto:default> show tables;
                      Table
--------------------------------------------------
 …… 這裏已省略其它未用到的表
impala::kudu_demo.movie
impala::kudu_demo.quote
tag_5
(16 rows)
Query 20191017_091246_00002_fxstp, FINISHED, 2 nodes
Splits: 36 total, 36 done (100.00%)
0:00 [16 rows, 773B] [76 rows/s, 3.63KB/s]

-- 3 在Presto中查詢Kudu表中的數據。注意如果表中有特殊字符(例如這裏又冒號),需要用引號括起來。
presto:default> SELECT m.id,m.movie_name,m.rating_num,m.rating_people,q.rank,q.quote FROM "impala::kudu_demo.movie" m
             -> LEFT JOIN "impala::kudu_demo.quote" q ON q.id=m.id
             -> ORDER BY m.rating_num DESC,m.rating_people DESC LIMIT 10;
   id    |                  movie_name                  | rating_num | rating_people | rank |             quote
---------+------------------------------------------+------------+---------------+------+------------------------
1292052 | 肖申克的救贖 The Shawshank Redemption (1994) |        9.7 |       1502851 |    1 | 希望讓人自由。
 1291546 | 霸王別姬 (1993)                              |        9.6 |       1112641 |    2 | 風華絕代。
 1296141 | 控方證人 Witness for the Prosecution (1957)  |        9.6 |        195362 |   29 | 比利·懷德滿分作品。
 1292063 | 美麗人生 La vita è bella (1997)              |        9.5 |        690618 |    5 | 最美的謊言。
1295124 | 辛德勒的名單 Schindler's List (1993)        |        9.5 |        613865 |    8 | 拯救一個人,就是拯救整個世界。
1295644 | 這個殺手不太冷 Léon (1994)                   |        9.4 |       1363430 |    3 | 怪蜀黍和小蘿莉不得不說的故事。
1292720 | 阿甘正傳 Forrest Gump (1994)                 |        9.4 |       1178003 |    4 | 一部美國近現代史。
 1292722 | 泰坦尼克號 Titanic (1997)                    |        9.4 |       1119405 |    7 | 失去的纔是永恆的。
 1293182 | 十二怒漢 12 Angry Men (1957)                 |        9.4 |        253408 |   36 | 1957年的理想主義。
 1291561 | 千與千尋 千と千尋の神隠し (2001)             |        9.3 |       1205228 |    6 | 最好的宮崎駿,最好的久石讓。
(10 rows)
Query 20191017_092306_00006_fxstp, FINISHED, 2 nodes
Splits: 117 total, 117 done (100.00%)
0:00 [500 rows, 1.71KB] [1.39K rows/s, 4.73KB/s]

6.1.4 Kafka

查詢Kafka的數據

presto:default> select _partition_id,_partition_offset,_segment_count,_key,_message from canal limit 3;
 _partition_id | _partition_offset | _segment_count | _key |
---------------+-------------------+----------------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
             0 |                45 |              1 | NULL | {"data":[{"loan_contract_id":"2","min_date":"2019-05-14","id":"3"}],"database":"adl_prewarning","es":1557798417000,"id":5242,"isDdl":false,"mysqlType":{"loan_contract_id":"varc
             0 |                46 |              2 | NULL | {"data":[{"loan_contract_id":"7","min_date":"2019-05-14","id":"7"}],"database":"adl_prewarning","es":1557827976000,"id":5542,"isDdl":false,"mysqlType":{"loan_contract_id":"varc
             0 |                47 |              3 | NULL | {"data":null,"database":"prewarning","es":1557978716000,"id":6116,"isDdl":true,"mysqlType":null,"old":null,"pkNames":null,"sql":"ALTER TABLE a ADD COLUMN age INT","sqlType"
(3 rows)
Query 20190519_193635_00009_huyim, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:46 [84 rows, 104KB] [1 rows/s, 2.25KB/s]

presto:default> select json_extract(_message, '$.type') from canal limit 3;
  _col0
----------
 "INSERT"
 "UPDATE"
 "ALTER"
(3 rows)
Query 20190519_194659_00012_huyim, FINISHED, 1 node
Splits: 35 total, 35 done (100.00%)
0:00 [84 rows, 104KB] [315 rows/s, 393KB/s]

6.2 JDBC 連接 Presto

6.2.1 新建Maven項目

在 idea 創建一個maven項目,

6.2.2 在pom.xml中引入依賴

    <dependencies>
        <!-- 0.219 com.facebook.presto已移至 io.prestosql.presto-jdbc -->
        <dependency>
            <groupId>io.prestosql</groupId>
            <artifactId>presto-jdbc</artifactId>
            <version>310</version>
        </dependency>
    </dependencies>

6.2.3 編寫代碼

創建java類,編寫Presto jdbc client代碼

package yore;

import io.prestosql.jdbc.PrestoConnection;
import io.prestosql.jdbc.PrestoStatement;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.ZoneId;
import java.util.TimeZone;

/**
 * JDBC訪問 Presto
 *
 * Created by yore on 2019/5/8 13:10
 */
public class PrestoJDBCClient {

    public static void printrow(ResultSet rs, int[] types) throws SQLException {
        for(int i=0; i<types.length; i++){
            System.out.print(" ");
            System.out.print(rs.getObject(i+1));
        }
        System.out.println("");
    }

    public static void connect() throws SQLException {
        // @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")));

        PrestoConnection conn = null;
        PrestoStatement statement = null;
        try {
            // 加載 Presto JDBC 驅動類
            Class.forName("io.prestosql.jdbc.PrestoDriver");

            /*
             * presto連接串:
             *      在 url 指定默認的 catalog 爲:system, 默認爲 Schema 爲: runtime ,
             *      使用的用戶名爲: presto-user,這個用戶名根據實際自己設定,用來標示執行 SQL 的用戶,雖然不會通過該用戶名進行身份認證,大師必須要寫
             *      密碼直接爲 null, 或者可以隨意指定一個任意密碼, Presto 是不會對密碼進行認證的。
             */
            conn = (PrestoConnection)DriverManager.getConnection(
                    // 端口查看config.properties文件中配置項http-server.http.port的值。catalog爲hive,Schema爲default,
                    "jdbc:presto://cdh6:8080/hive/default",
                    "presto-user",
                    null
            );

            statement = (PrestoStatement)conn.createStatement();

            String sql = "select * from nodes";
            sql = "show tables";
            sql = " select count(*) from dw_orders_his";
            long start = System.currentTimeMillis();
            ResultSet rs = statement.executeQuery(sql);


            int cn = rs.getMetaData().getColumnCount();
            int[] types = new int[cn];
            for(int i=0; i<cn; i++){
                types[i] = rs.getMetaData().getColumnType(i+1);
            }

            while (rs.next()){
                printrow(rs, types);
            }
            System.out.println("-------");
            System.out.println("用時:" + (System.currentTimeMillis()-start) + "(ms)");

        }catch (ClassNotFoundException e){
            e.printStackTrace();
        }catch (SQLException e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws SQLException {
        connect();
    }
}

6.2.4 運行

 6
-------
用時:621(ms)

Process finished with exit code 0

6.3 Kafka Connector

其他的Connectors 可查看官網,這裏主要以Kafka Connector爲例。

下載腳本,

curl -o kafka-tpch http://repo1.maven.org/maven2/de/softwareforge/kafka_tpch_0811/1.0/kafka_tpch_0811-1.0.sh
chmod +x kafka-tpch

運行腳本,創建Topic和加載一些數據

./kafka-tpch load --brokers cdh3:9092,cdh2:9092,cdh1:9092 --prefix ptch. --tpch-type tiny

修改kafka.properties爲如下

connector.name=kafka
kafka.default-schema=default
kafka.table-names=ptch.customer,ptch.lineitem,ptch.orders,ptch.nation,ptch.part,ptch.partsupp,ptch.region,ptch.supplier
kafka.nodes=cdh1:9092,cdh2:9092,cdh3:9092
# d(天)、h(小時)、m(分鐘)、s(秒)、ms(毫秒)、us(微秒)、ns(納秒)、
kafka.connect-timeout=10s
kafka.hide-internal-columns=false

重啓Presto

bin/launcher restart

連接 Presto Cli

[root@cdh6 bin]# ./presto-cli-0.219-executable.jar --catalog kafka --schema ptch
presto:ptch> show tables;
  Table
----------
 customer
 lineitem
 nation
 orders
 part
 partsupp
 region
 supplier
(8 rows)
Query 20190519_205355_00002_vqku8, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:00 [8 rows, 166B] [17 rows/s, 355B/s]

6.3.1 基本查詢

presto:ptch> describe customer;

presto:ptch> select count(*) from customer;

presto:ptch> select _message from customer limit 5;

presto:ptch> select sum(cast(json_extract_scalar(_message,'$.accountBalance') as double)) from customer limit 10;

6.3.2 添加表定義文件

presto-server-0.219/etc/kafka/ 下新建 ptch.customer.json 並重啓 Presto

{
  "tableName": "customer",
  "schemaName": "ptch",
  "topicName": "ptch.customer",
  "key": {
    "dataFormat": "raw",
    "fields": [
      {
        "name": "kafka_key",
        "dataFormat": "LONG",
        "type": "BIGINT",
        "hidden": "false"
      }
    ]
  }
}

重啓: bin/launcher restart

查看錶信息,可以看到多了一列 kafka_key

bin/presto-cli-0.219-executable.jar --catalog kafka --schema ptch

presto:ptch> desc customer;
      Column       |  Type   | Extra |                   Comment
-------------------+---------+-------+---------------------------------------------
 kafka_key         | bigint  |       |
 _partition_id     | bigint  |       | Partition Id
 _partition_offset | bigint  |       | Offset for the message within the partition
 _segment_start    | bigint  |       | Segment start offset
 _segment_end      | bigint  |       | Segment end offset
 _segment_count    | bigint  |       | Running message count per segment
 _message_corrupt  | boolean |       | Message data is corrupt
 _message          | varchar |       | Message text
 _message_length   | bigint  |       | Total number of message bytes
 _key_corrupt      | boolean |       | Key data is corrupt
 _key              | varchar |       | Key text
 _key_length       | bigint  |       | Total number of key bytes
(12 rows)
Query 20190520_014112_00002_i4shm, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:01 [12 rows, 1.05KB] [15 rows/s, 1.37KB/s]

presto:ptch> select kafka_key from customer order by kafka_key limit 10;
 kafka_key
-----------
         0
         1
         2
         3
         4
         5
         6
         7
         8
         9
(10 rows)
Query 20190520_014623_00007_i4shm, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:00 [1.5K rows, 411KB] [7.07K rows/s, 1.89MB/s]

6.3.3 將 message 中所有的值映射到不同列

再次更新 presto-server-0.219/etc/kafka/ 下新建 ptch.customer.json 並重啓 Presto爲:

{
  "tableName": "customer",
  "schemaName": "ptch",
  "topicName": "ptch.customer",
  "key": {
    "dataFormat": "raw",
    "fields": [
      {
        "name": "kafka_key",
        "dataFormat": "LONG",
        "type": "BIGINT",
        "hidden": "false"
      }
    ]
  },
  "message": {
    "dataFormat": "json",
    "fields": [
      {
        "name": "row_number",
        "mapping": "rowNumber",
        "type": "BIGINT"
      },
      {
        "name": "customer_Key",
        "mapping": "customerKey",
        "type": "BIGINT"
      },
      {
        "name": "name",
        "mapping": "name",
        "type": "VARCHAR"
      },
      {
        "name": "address",
        "mapping": "address",
        "type": "VARCHAR"
      },
      {
        "name": "nation_key",
        "mapping": "nationKey",
        "type": "BIGINT"
      },
      {
        "name": "phone",
        "mapping": "phone",
        "type": "VARCHAR"
      },
      {
        "name": "account_balance",
        "mapping": "accountBalance",
        "type": "DOUBLE"
      },
      {
        "name": "market_segment",
        "mapping": "marketSegment",
        "type": "VARCHAR"
      },
      {
        "name": "comment",
        "mapping": "comment",
        "type": "VARCHAR"
      }
    ]
  }
}

再次查看錶信息,可以看到我們前面配置的列已經添加上去了

presto:ptch> desc customer;
      Column       |  Type   | Extra |                   Comment
-------------------+---------+-------+---------------------------------------------
 kafka_key         | bigint  |       |
 row_number        | bigint  |       |
 customer_key      | bigint  |       |
 name              | varchar |       |
 address           | varchar |       |
 nation_key        | bigint  |       |
 phone             | varchar |       |
 account_balance   | double  |       |
 market_segment    | varchar |       |
 comment           | varchar |       |
 _partition_id     | bigint  |       | Partition Id
 _partition_offset | bigint  |       | Offset for the message within the partition
 _segment_start    | bigint  |       | Segment start offset
 _segment_end      | bigint  |       | Segment end offset
 _segment_count    | bigint  |       | Running message count per segment
 _message_corrupt  | boolean |       | Message data is corrupt
 _message          | varchar |       | Message text
 _message_length   | bigint  |       | Total number of message bytes
 _key_corrupt      | boolean |       | Key data is corrupt
 _key              | varchar |       | Key text
 _key_length       | bigint  |       | Total number of key bytes
(21 rows)
Query 20190520_020241_00003_r6kqj, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:01 [21 rows, 1.64KB] [18 rows/s, 1.47KB/s]

presto:ptch> select * from customer limit 5;
 kafka_key | row_number | customer_key |        name        |            address             | nation_key |      phone      | account_balance | market_segment |                                                comment                                                 | _part
-----------+------------+--------------+--------------------+--------------------------------+------------+-----------------+-----------------+----------------+--------------------------------------------------------------------------------------------------------+------
         0 |          1 |            1 | Customer#000000001 | IVhzIApeRb ot,c,E              |         15 | 25-989-741-2988 |          711.56 | BUILDING       | to the even, regular platelets. regular, ironic epitaphs nag e                                         |
         1 |          2 |            2 | Customer#000000002 | XSTf4,NCwDVaWNe6tEgvwfmRchLXak |         13 | 23-768-687-3665 |          121.65 | AUTOMOBILE     | l accounts. blithely ironic theodolites integrate boldly: caref                                        |
         2 |          3 |            3 | Customer#000000003 | MG9kdTD2WBHm                   |          1 | 11-719-748-3364 |         7498.12 | AUTOMOBILE     |  deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov |
         3 |          4 |            4 | Customer#000000004 | XxVSJsLAGtn                    |          4 | 14-128-190-5944 |         2866.83 | MACHINERY      |  requests. final, regular ideas sleep final accou                                                      |
         4 |          5 |            5 | Customer#000000005 | KvpyuHCplrB84WgAiGV6sYpZq7Tj   |          3 | 13-750-942-6364 |          794.47 | HOUSEHOLD      | n accounts will have to unwind. foxes cajole accor                                                     |
(5 rows)
Query 20190520_020359_00004_r6kqj, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:35 [1.5K rows, 411KB] [42 rows/s, 11.7KB/s]

presto:ptch> select sum(account_balance) from customer limit 10;
       _col0
-------------------
 6681865.590000002
(1 row)
Query 20190520_020616_00005_r6kqj, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:01 [1.5K rows, 411KB] [2.75K rows/s, 755KB/s]


6.4 使用實時數據

6.4.1 在Kafka集羣上創建一個Topic

kafka-topics --create --zookeeper cdh1:2181,cdh2:2181,cdh3:2181 --replication-factor 1 --partitions 1 --topic test.weblog

6.4.2 編寫一個Kafka生產者

TestProducer
推送到Kafka的數據格式如下:

{
  "user": {
    "name": "Bob",
    "gender": "male"
  },
  "time": 1558394886956,
  "website": "www.twitter.com"
}

6.4.3 在Presto中創建表

presto-server-0.219/etc/catalog/kafka.properties配置文件的kafka.table-names中添加上Kafka Topic test.weblog

presto-server-0.219/etc/kafka/下添加Kafka數據配置json文件 test.weblog.json,在這個版本中還不支持時間戳,配置如下:

{
  "tableName": "weblog",
  "schemaName": "test",
  "topicName": "test.weblog",
  "key": {
    "dataFormat": "raw",
    "fields": [
      {
        "name": "kafka_key",
        "dataFormat": "LONG",
        "type": "BIGINT",
        "hidden": "false"
      }
    ]
  },
  "message": {
    "dataFormat": "json",
    "fields": [
      {
        "name": "name",
        "mapping": "user/name",
        "type": "VARCHAR"
      },
      {
        "name": "gender",
        "mapping": "user/gender",
        "type": "VARCHAR"
      },
      {
        "name": "time",
        "mapping": "time",
        "type": "BIGINT"
      },
      {
        "name": "website",
        "mapping": "website",
        "type": "VARCHAR"
      }
    ]
  }
}

6.4.4 重啓Presto,進行如下查詢數據

# 重啓
bin/launcher restart

# 進入cli,連接Kafka
./presto-cli-0.219-executable.jar --catalog kafka --schema test

進行如下查詢(此時可以把Kafka生產者運行,模擬持續的數據源):
JSON Functions and Operators
Date and Time Functions and Operators

presto:test> show tables;
 Table  
--------
 weblog 
(1 row)
Query 20190521_160458_00002_gf883, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:00 [1 rows, 20B] [2 rows/s, 52B/s]

presto:test> desc weblog;
      Column       |   Type    | Extra |                   Comment                   
-------------------+-----------+-------+---------------------------------------------
 kafka_key         | bigint    |       |                                             
 name              | varchar   |       |                                             
 gender            | varchar   |       |                                             
 time              | timestamp |       |                                             
 website           | varchar   |       |                                             
 _partition_id     | bigint    |       | Partition Id                                
 _partition_offset | bigint    |       | Offset for the message within the partition 
 _segment_start    | bigint    |       | Segment start offset                        
 _segment_end      | bigint    |       | Segment end offset                          
 _segment_count    | bigint    |       | Running message count per segment           
 _message_corrupt  | boolean   |       | Message data is corrupt                     
 _message          | varchar   |       | Message text                                
 _message_length   | bigint    |       | Total number of message bytes               
 _key_corrupt      | boolean   |       | Key data is corrupt                         
 _key              | varchar   |       | Key text                                    
 _key_length       | bigint    |       | Total number of key bytes                   
(16 rows)
Query 20190521_160636_00004_gf883, FINISHED, 1 node
Splits: 19 total, 19 done (100.00%)
0:00 [16 rows, 1.27KB] [54 rows/s, 4.33KB/s]


presto:test> select count(*) from weblog;
 _col0 
-------
    13 
(1 row)
Query 20190521_161116_00006_gf883, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:00 [13 rows, 1.17KB] [78 rows/s, 7.1KB/s]
presto:test> select count(*) from weblog;
 _col0 
-------
    17 
(1 row)
Query 20190521_161120_00007_gf883, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:00 [17 rows, 1.53KB] [105 rows/s, 9.5KB/s]
presto:test> select count(*) from weblog;
 _col0 
-------
    20 
(1 row)
Query 20190521_161129_00008_gf883, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:00 [20 rows, 1.79KB] [102 rows/s, 9.16KB/s]


presto:test> select kafka_key,name,gender,time,website from weblog limit 10;
 kafka_key |  name  | gender |     time      |     website      
-----------+--------+--------+---------------+------------------
         0 | Bob    | male   | 1558394879467 | www.jd.com       
         1 | Cara   | female | 1558394880952 | www.linkin.com   
         2 | David  | male   | 1558394881952 | www.facebook.com 
         3 | Bob    | male   | 1558394882952 | www.linkin.com   
         4 | Edward | male   | 1558394883952 | www.google.com   
         5 | Alice  | female | 1558394884952 | www.facebook.com 
         6 | Cara   | female | 1558394885952 | www.facebook.com 
         7 | Bob    | male   | 1558394886956 | www.twitter.com  
         0 | Cara   | female | 1558455070939 | www.google.com   
         1 | David  | male   | 1558455072607 | www.facebook.com 
(10 rows)
Query 20190521_162907_00003_y7pq6, FINISHED, 1 node
Splits: 18 total, 18 done (100.00%)
0:00 [20 rows, 1.79KB] [62 rows/s, 5.62KB/s]

presto:test> select kafka_key,name,gender,from_unixtime(time/1000),website from weblog limit 10;
 kafka_key |  name  | gender |          _col3          |     website      
-----------+--------+--------+-------------------------+------------------
         0 | Bob    | male   | 2019-05-21 07:27:59.000 | www.jd.com       
         1 | Cara   | female | 2019-05-21 07:28:00.000 | www.linkin.com   
         2 | David  | male   | 2019-05-21 07:28:01.000 | www.facebook.com 
         3 | Bob    | male   | 2019-05-21 07:28:02.000 | www.linkin.com   
         4 | Edward | male   | 2019-05-21 07:28:03.000 | www.google.com   
         5 | Alice  | female | 2019-05-21 07:28:04.000 | www.facebook.com 
         6 | Cara   | female | 2019-05-21 07:28:05.000 | www.facebook.com 
         7 | Bob    | male   | 2019-05-21 07:28:06.000 | www.twitter.com  
         0 | Cara   | female | 2019-05-22 00:11:10.000 | www.google.com   
         1 | David  | male   | 2019-05-22 00:11:12.000 | www.facebook.com 
(10 rows)
Query 20190521_163618_00006_y7pq6, FINISHED, 1 node
Splits: 34 total, 34 done (100.00%)
0:00 [20 rows, 1.79KB] [48 rows/s, 4.32KB/s]




My GitHub:presto-jdbc源碼   |    readme

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