從 0 到 1 學習 Presto,這一篇就夠了!
持之以恒,貴在堅持,每天進步一點點!
前言
Presto 作為現(xiàn)在在企業(yè)中流行使用的即席查詢框架,已經(jīng)在不同的領(lǐng)域得到了越來越多的應(yīng)用。本期內(nèi)容,我會從一個初學者的角度,帶著大家從 0 到 1 學習 Presto,希望大家能夠有所收獲!

文章目錄
前言
1. Presto簡介
1. 1 Presto概念
1.2 Presto 應(yīng)用場景
1.3 Presto架構(gòu)
1.4 Presto 數(shù)據(jù)模型
1.5 Presto 優(yōu)缺點
1.6 Presto、Impala性能比較
1.7 官網(wǎng)地址
1.8 Prestodb VS Prestosql(trino)
2. Presto安裝部署
2.1 prestosql 版本的選擇
2.2 集群安裝規(guī)劃
2.3 Presto Server 的安裝
2.4 Node Properties 配置
2.5 JVM Config 配置
2.6 Config Properties 配置
2.7 Log Properties 配置
2.8 Catalog Properties 配置
2.9 分發(fā)安裝目錄到集群中其它節(jié)點上
2.10 修改 node.id
2.11 修改 work 節(jié)點的配置信息
2.12 啟動服務(wù)
3、Presto 命令行 Client 的安裝
4、Presto 的基本使用
5、Presto可視化客戶端的安裝
6、Presto的優(yōu)化
6.1 數(shù)據(jù)存儲
6.2 SQL查詢
6.3 注意事項
6.4 可能會踩的坑
巨人的肩膀
小結(jié)
彩蛋
1. Presto簡介
1. 1 Presto概念
Presto是 Facebook 推出的一個開源的分布式SQL查詢引擎,數(shù)據(jù)規(guī)??梢灾С諫B到PB級,主要應(yīng)用于處理秒級查詢的場景。Presto 的設(shè)計和編寫完全是為了解決像 Facebook 這樣規(guī)模的商業(yè)數(shù)據(jù)倉庫的交互式分析和處理速度的問題。
注意: 雖然 Presto 可以解析 SQL,但它不是一個標準的數(shù)據(jù)庫。不是 MySQL、Oracle 的代替品,也不能用來處理在線事務(wù)(OLTP)。
1.2 Presto 應(yīng)用場景
Presto 支持在線數(shù)據(jù)查詢,包括 Hive,關(guān)系數(shù)據(jù)庫(MySQL、Oracle)以及專有數(shù)據(jù)存儲。一條 Presto 查詢可以將多個數(shù)據(jù)源的數(shù)據(jù)進行合并,可以跨越整個組織進行分析。
Presto 主要用來處理 響應(yīng)時間小于 1 秒到幾分鐘的場景 。
1.3 Presto架構(gòu)
Presto 是一個運行在多臺服務(wù)器上的分布式系統(tǒng)。完整安裝包括一個 Coordinator 和多 個 Worker。由客戶端提交查詢,從 Presto 命令行 CLI 提交到 Coordinator。Coordinator 進行 解析,分析并執(zhí)行查詢計劃,然后分發(fā)處理隊列到 Worker 。
Presto 有兩類服務(wù)器:Coordinator 和 Worker
1) Coordinator
Coordinator 服務(wù)器是用來解析語句,執(zhí)行計劃分析和管理 Presto 的 Worker 節(jié)點。Presto 安裝必須有一個 Coordinator 和多個 Worker。如果用于開發(fā)環(huán)境和測試,則一個 Presto 實例 可以同時擔任這兩個角色。
Coordinator 跟蹤每個 Work 的活動情況并協(xié)調(diào)查詢語句的執(zhí)行。Coordinator 為每個查詢建立模型,模型包含多個Stage,每個Stage再轉(zhuǎn)為Task 分發(fā)到不同的 Worker 上執(zhí)行。
Coordinator 與 Worker、Client 通信是通過 REST API。
2)Worker
Worker 是負責執(zhí)行任務(wù)和處理數(shù)據(jù)。Worker 從 Connector 獲取數(shù)據(jù)。Worker 之間會交換中間數(shù)據(jù)。Coordinator 是負責從 Worker 獲取結(jié)果并返回最終結(jié)果給 Client。
當 Worker 啟動時,會廣播自己去發(fā)現(xiàn) Coordinator,并告知 Coordinator 它是可用,隨時 可以接受 Task。
Worker 與 Coordinator、Worker 通信是通過 REST API。
3)數(shù)據(jù)源
貫穿下文,你會看到一些術(shù)語:Connector、Catelog、Schema 和 Table。這些是 Presto 特定的數(shù)據(jù)源
Connector
Connector 是適配器,用于 Presto 和數(shù)據(jù)源(如 Hive、RDBMS)的連接。你可以認為 類似 JDBC 那樣,但卻是 Presto 的 SPI 的實現(xiàn),使用標準的 API 來與不同的數(shù)據(jù)源交互。
Presto 有幾個內(nèi)建 Connector:JMX 的 Connector、System Connector(用于訪問內(nèi)建的 System table)、Hive 的 Connector、TPCH(用于 TPC-H 基準數(shù)據(jù))。還有很多第三方的 Connector,所以 Presto 可以訪問不同數(shù)據(jù)源的數(shù)據(jù)。
每個 Catalog 都有一個特定的 Connector。如果你使用 catelog 配置文件,你會發(fā)現(xiàn)每個 文件都必須包含 connector.name 屬性,用于指定 catelog 管理器(創(chuàng)建特定的 Connector 使用)。一個或多個 catelog 用同樣的 connector 是訪問同樣的數(shù)據(jù)庫。例如,你有兩個 Hive 集群。你可以在一個 Presto 集群上配置兩個 catelog,兩個 catelog 都是用 Hive Connector,從而達 到可以查詢兩個 Hive 集群。
Catelog
一個 Catelog 包含 Schema 和 Connector 。例如,你配置JMX 的 catelog,通過JXM Connector 訪問 JXM 信息。當你執(zhí)行一條 SQL 語句時,可以同時運行在多個 catelog。
Presto 處理 table 時,是通過表的完全限定(fully-qualified)名來找到 catelog。例如, 一個表的權(quán)限定名是 hive.test_data.test,則 test 是表名,test_data 是 schema,hive 是 catelog。
Catelog 的定義文件是在 Presto 的配置目錄中。
Schema
Schema 是用于組織 table。把 catelog 和 schema 結(jié)合在一起來包含一組的表。當通過Presto 訪問 hive 或 Mysq 時,一個 schema 會同時轉(zhuǎn)為 hive 和 mysql 的同等概念。
Table
Table 跟關(guān)系型的表定義一樣,但數(shù)據(jù)和表的映射是交給 Connector。
1.4 Presto 數(shù)據(jù)模型
1)Presto 采取三層表結(jié)構(gòu):
Catalog:對應(yīng)某一類數(shù)據(jù)源,例如 Hive 的數(shù)據(jù),或 MySql 的數(shù)據(jù)
Schema:對應(yīng) MySql 中的數(shù)據(jù)庫
Table:對應(yīng) MySql 中的表
2)Presto 的存儲單元包括:
Page:多行數(shù)據(jù)的集合,包含多個列的數(shù)據(jù),內(nèi)部僅提供邏輯行,實際以列式存儲。
Block:一列數(shù)據(jù),根據(jù)不同類型的數(shù)據(jù),通常采取不同的編碼方式,了解這些編碼方式,有助于自己的存儲系統(tǒng)對接 presto。
3)不同類型的 Block:
(1)Array 類型 Block,應(yīng)用于固定寬度的類型,例如 int,long,double。block 由兩部分組成:
boolean valueIsNull[]表示每一行是否有值。T values[]每一行的具體值
(2)可變寬度的 Block,應(yīng)用于 String 類數(shù)據(jù),由三部分信息組成
Slice:所有行的數(shù)據(jù)拼接起來的字符串int offsets[]:每一行數(shù)據(jù)的起始偏移位置。每一行的長度等于下一行的起始偏移減去當 前行的起始偏移。boolean valueIsNull[]: 表示某一行是否有值。如果有某一行無值,那么這一行的偏移量 等于上一行的偏移量。
(3)固定寬度的 String 類型的 block,所有行的數(shù)據(jù)拼接成一長串 Slice,每一行的長度固定。
(4)字典 block:對于某些列,distinct 值較少,適合使用字典保存。主要有兩部分組成:
字典,可以是任意一種類型的 block(甚至可以嵌套一個字典 block),block 中的每一行按照順序排序編號。
int ids[]表示每一行數(shù)據(jù)對應(yīng)的 value 在字典中的編號。在查找時,首先找到某一行的 id, 然后到字典中獲取真實的值。
1.5 Presto 優(yōu)缺點
學習一個新的框架,免不了來探討一下它的優(yōu)缺點:
通過下面一張圖,我們來看看 Presto 中 SQL 運行過程:MapReduce vs Presto
我們可以很明顯地感受到,Presto 使用內(nèi)存計算,減少與硬盤交互
1.5.1 優(yōu)點
1)Presto 與 Hive 對比,都能夠處理 PB 級別的海量數(shù)據(jù)分析,但 Presto 是基于內(nèi)存運算,減少沒必要的硬盤 IO,所以更快。
2)能夠連接多個數(shù)據(jù)源,跨數(shù)據(jù)源連表查,如從 Hive 查詢大量網(wǎng)站訪問記錄,然后從 Mysql 中匹配出設(shè)備信息。
3)部署也比 Hive 簡單,因為 Hive 是基于 HDFS 的,需要先部署 HDFS。
找了張對比圖,大家感受下: 
1.5.2 缺點
1)雖然能夠處理 PB 級別的海量數(shù)據(jù)分析,但不是代表 Presto 把 PB 級別都放在內(nèi)存中計算的。而是根據(jù)場景,如 count,avg 等聚合運算,是邊讀數(shù)據(jù)邊計算,再清內(nèi)存,再讀數(shù)據(jù)再計算,這種耗的內(nèi)存并不高。但是連表查,就可能產(chǎn)生大量的臨時數(shù)據(jù),因此速度會變慢,反而 Hive此時會更擅長。
2)為了達到實時查詢,可能會想到用它直連 MySql 來操作查詢,這效率并不會提升, 瓶頸依然在 MySql,此時還引入網(wǎng)絡(luò)瓶頸,所以會比原本直接操作數(shù)據(jù)庫要慢。
1.6 Presto、Impala性能比較
Presto 和 Impala這兩種典型的內(nèi)存數(shù)據(jù)庫之間具體的性能測試比較就不詳細展開敘述,感興趣可以去看這篇鏈接:https://blog.csdn.net/u012551524/article/details/79124532
我就說下總結(jié)的結(jié)論:
他們的共同點就是吃內(nèi)存,當然在內(nèi)存充足的情況下,并且有規(guī)模適當?shù)募?,性能?yīng)該會更可觀。并且從幾次性能的比較查詢來看,Impala性能稍領(lǐng)先于presto,但是presto在數(shù)據(jù)源支持上非常豐富,包括hive、圖數(shù)據(jù)庫、傳統(tǒng)關(guān)系型數(shù)據(jù)庫、Redis等
大家也可以根據(jù)上面的鏈接,自己也嘗試去做下對比測試。
1.7 官網(wǎng)地址
就在 2020 年 12 月 27 日,prestosql 與 facebook 正式分裂,并改名為trino。分裂之前和之后的官網(wǎng)分別是:https://prestosql.io/ 和 https://trino.io。

1.8 Prestodb VS Prestosql(trino)
根據(jù)目前社區(qū)活躍度和使用廣泛度,更加推薦 prestosql。具體的區(qū)別詳見:
http://armsword.com/2020/05/02/the-difference-between-prestodb-and-prestosql/
2. Presto安裝部署
2.1 prestosql 版本的選擇
在 presto330 版本里已經(jīng)提到,jdk8 只支持到 2020-03 月發(fā)行的版本.詳情參考:https://prestosql.io/docs/current/release/release-330.html。在 2020 年 4 月 8 號 presto 社區(qū)發(fā)布的 332 版本開始,需要 jdk11 的版本.由于現(xiàn)在基本都使 用的是 jdk8,所以我們選擇 presto315 版本的,此版本在 jdk8 的環(huán)境下是可用的。如果我們生產(chǎn)環(huán)境是 jdk8,但是又想使用新版的 presto,可以為 presto 單獨指定 jdk11 也可使用。
2.2 集群安裝規(guī)劃
| host | coordinator | worker |
|---|---|---|
| node01 | √ | × |
| node02 | × | √ |
| node03 | × | √ |
2.3 Presto Server 的安裝
1、安裝包下載地址:
https://repo1.maven.org/maven2/io/prestosql/presto-server/315/presto-server-315.tar.gz
2、將 presto-server-315.tar.gz 上傳到服務(wù)器上,這里導入到 node01 服務(wù)器上的 /export/software/目錄下,并解壓至 /export/servers/目錄下:
[root@node01 software]# tar -zvxf presto-server-315.tar.gz -C /export/servers/
3、創(chuàng)建 presto 的數(shù)據(jù)目錄 ( presto 集群的每臺機器都要創(chuàng)建),用來存儲日志這些
[root@node01 presto-server-315]# mkdir -p /file/data/presto
4、在安裝目錄 /export/servers/presto-server-315 下創(chuàng)建 etc 目錄,用來存放各種配置文件
[node01@node01 presto-server-315]# mkdir etc
2.4 Node Properties 配置
在 /export/servers/presto-server-315/etc 路徑下,配置 node 屬性(注意:集群中每臺 presto 的 node.id 必須不一樣,后面需要修改集群中其它節(jié)點的 node.id 值)
[root@node01 etc]# vim node.properties
#環(huán)境名稱,自己任取.集群中的所有 Presto 節(jié)點必須具有相同的環(huán)境名稱.
node.environment=develop
#支持字母,數(shù)字.對于每個節(jié)點,這必須是唯一的.這個標識符應(yīng)該在重新啟動或升級 Presto 時保持一致
node.id=1
#指定 presto 的日志和其它數(shù)據(jù)的存儲目錄,自己創(chuàng)建前面創(chuàng)建好的數(shù)據(jù)目錄
node.data-dir=/file/data/presto
2.5 JVM Config 配置
在/exports/servers/presto-server-315/etc 目錄下添加 jvm.config 配置文件,并填入如下內(nèi)容
#參考官方給的配置,根據(jù)自身機器實際內(nèi)存進行配置
-server
#最大 jvm 內(nèi)存
-Xmx16G
#指定 GC 的策略
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError
-XX:ReservedCodeCacheSize=256M
2.6 Config Properties 配置
Presto 是由一個 coordinator 節(jié)點和多個 worker 節(jié)點組成。由于在單獨一臺服務(wù)器上配置 coordinator ,有利于提高性能,所以在 node01上配置成 coordinator,在 node02,node03 上配 置為 worker(如果實際機器數(shù)量不多的話可以將在協(xié)調(diào)器上部署 worker.)在 /export/servers/presto-server-315/etc目錄下添加 config.properties 配置文件
# 該節(jié)點是否作為 coordinator,如果是 true 就允許該 Presto 實例充當協(xié)調(diào)器
coordinator=true
# 允許在協(xié)調(diào)器上調(diào)度工作(即配置 worker 節(jié)點).為 false 就是不允許.對于較大的集群,協(xié)調(diào)器上的處理工作可能會影響查詢性能,因為機器的資源無法用于調(diào)度,管理和監(jiān)視查詢執(zhí)行的關(guān)鍵任務(wù)
# 如果需要在協(xié)調(diào)器所在節(jié)點配置 worker 節(jié)點改為 true 即可
node-scheduler.include-coordinator=false
# 指定 HTTP 服務(wù)器的端口.Presto 使用 HTTP 進行所有內(nèi)部和外部通信
http-server.http.port=8080
# 每個查詢可以使用的最大分布式內(nèi)存量
query.max-memory=50GB
#查詢可在任何一臺計算機上使用的最大用戶內(nèi)存量
query.max-memory-per-node=1GB
# 查詢可在任何一臺計算機上使用的最大用戶和系統(tǒng)內(nèi)存量,其中系統(tǒng)內(nèi)存是讀取器,寫入器和網(wǎng)絡(luò)緩沖區(qū)等在執(zhí)行期間使用的內(nèi)存
query.max-total-memory-per-node=2GB
# discover-server 是 coordinator 內(nèi)置的服務(wù),負責監(jiān)聽 worker
discovery-server.enabled=true
# 發(fā)現(xiàn)服務(wù)器的 URI.因為已經(jīng)在 Presto 協(xié)調(diào)器中啟用了 discovery,所以這應(yīng)該是 Presto 協(xié)調(diào)器的 URI
discovery.uri=http://node01:8080
2.7 Log Properties 配置
日志配置文件:etc/log.properties。類似Java的日志級別,包括 INFO、DEBUG、ERROR。
com.facebook.presto=INFO
2.8 Catalog Properties 配置
Presto 可以支持多個數(shù)據(jù)源,在 Presto 里面叫 catalog,這里以配置支持 Hive 的數(shù)據(jù)源為例,配置一個 Hive 的 catalog :
#在 etc 目錄下創(chuàng)建 catalog 目錄
[root@node01 etc]# mkdir catalog
Hive 的 catalog:
[root@node01 catalog]# vim hive.properties
#代表 hadoop2 代版本,并不是單單指 hadoop2.x 的版本,而是 hadoop 第二代.固定寫法
connector.name=node02
#指定 hive 的 metastore 的地址(hive 必須啟用 metastore)
hive.metastore.uri=thrift://node01:9083
#如果 hdfs 是高可用必須增加這個配置.如果不是高可用,可省略.如果 Presto 所在的節(jié)點>沒 有安裝 Hadoop,需要從其它 hadoop 節(jié)點復制這些文件到 Presto 的節(jié)點
hive.config.resources=/export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/core-site.xml, /export/servers/hadoop-2.6.0-cdh5.14.0/etc/hadoop/hdfs-site.xml
hive.allow-drop-table=true
hive.storage-format=ORC
hive.metastore-cache-ttl=1s
hive.metastore-refresh-interval=1s
hive.metastore-timeout=35m
hive.max-partitions-per-writers=1000
2.9 分發(fā)安裝目錄到集群中其它節(jié)點上
將 node01 上配置好的 presto 安裝包分發(fā)到集群中的其它節(jié)點(這里使用的是自己寫的分發(fā)腳本)
[root@node01 servers]# xsync script /export/servers/presto-server-315/
2.10 修改 node.id
修改 node02 和 node03 機器上 node.properties 配置文件中的 node.id (因為每臺機器 node.id 必須要不一樣)
[root@node02 etc]# vim node.properties
node.id=2
[root@node03 etc]# vim node.properties
node.id=3
2.11 修改 work 節(jié)點的配置信息
修改 worker 節(jié)點(即 linux122 和 linux123 機器)上的 config.properties 配置文件里面的配置內(nèi)容與 coordinator 所在的節(jié)點是不一樣的
#該節(jié)點是否作為 coordinator,因為是 worker 節(jié)點,這里是 false
coordinator=false
#訪問端口,可以自己指定
http-server.http.port=8080
#每個查詢可以使用的最大分布式內(nèi)存量
query.max-memory=50GB
#查詢可在任何一臺計算機上使用的最大用戶內(nèi)存量
query.max-memory-per-node=1GB
#查詢可在任何一臺計算機上使用的最大用戶和系統(tǒng)內(nèi)存量,其中系統(tǒng)內(nèi)存是讀取器,寫 入器和網(wǎng)絡(luò)緩沖區(qū)等在執(zhí)行期間使用的內(nèi)存
query.max-total-memory-per-node=2GB
#指定 discovery-server 的地址,這樣 worker 才能找到它.與上面的端口須一致
discovery.uri=http://node01:8080
2.12 啟動服務(wù)
啟動腳本在安裝目錄的bin/launcher目錄下,我們可以使用如下命令作為一個后臺進程啟動:
bin/launcher start
另外,也可以用在前臺啟動的方式運行,日志和目錄輸出將會寫入到 stdout/stderr(可以使用類似daemontools的工具捕捉這兩個數(shù)據(jù)流)
bin/launcher run
啟動完之后,日志將會寫在var/log目錄下,該目錄下有如下文件:
launcher.log:這個日志文件由 launcher 創(chuàng)建,并且server的stdout和stderr都被重定向到了這個日志文件中。這份日志文件中只會有很少的信息,包括:
在server日志系統(tǒng)初始化的時候產(chǎn)生的日志和JVM產(chǎn)生的診斷和測試信息。
server.log:這個是 Presto 使用的主要日志文件。一般情況下,該文件中將會包括server初始化失敗時產(chǎn)生的相關(guān)信息。
http-request.log:這是HTTP請求的日志文件,包括server收到的每個HTTP請求信息。
啟動成功之后,我們可以通過jps查看到多了一個 PrestoServer 的進程。
[root@node01 etc]# jps
6051 PrestoServer
此時我們就可以通過ip:端口的方式訪問到 presto 的 webui 界面。
關(guān)于 webui 中各項指標的含義,我整理了2張圖,大家可以借鑒一下

另外,關(guān)于 Stage,Task 階段的各參數(shù)指標含義,就不細講了,更多內(nèi)容詳情見官網(wǎng)....
3、Presto 命令行 Client 的安裝
Presto 的 命令行 Client 下載步驟也很簡單:
1、下載 Presto 的客戶端(下載 presto 對應(yīng)的版本)??https://repo1.maven.org/maven2/io/prestosql/presto-cli/315/presto-cli-315-executable.jar
2、將 presto-cli-315-executable.jar 上傳至服務(wù)器,放在 node01 的 /export/servers/presto-server- 315/bin 目錄下
3、為方便使用,修改 jar 包名稱為 presto
[root@node01 bin]$ mv presto-cli-315-executable.jar presto
4. 給文件增加執(zhí)行權(quán)限
[root@node01 bin]# chmod +x presto
4、Presto 的基本使用
1、 啟動 presto 客戶端并選擇連接的數(shù)據(jù)源(這里以 hive 為例)
[root@node01 bin]$ ./presto \
--server node01:8080 \
--catalog hive \(可選)
--schema test \(可選)
--user xiaobai (可選)
說明:
-- server 指定的是 coordinator 的地址
-- catalog 指定的是連接的數(shù)據(jù)源.(跟配置文件里面的名稱一致)
-- schema 指定的是連接哪個數(shù)據(jù)庫,這里是 test 數(shù)據(jù)庫
-- user 指定的是連接使用哪個用戶,這里是xiaobai
2、Presto 命令行操作
#查看所有的數(shù)據(jù)庫
presto:test> show schemas;
#查看某個庫下的所有表
presto:test> show tables;
#查看一條 sql 查詢(6 億多條數(shù)據(jù)比 hive 快很多)
presto:test> select count(1) from test.test_hive;
_col0
-----------
620756992
5、Presto可視化客戶端的安裝
Presto 可視化客戶端有多種,這里我們選擇使用 yanagishima-20.0 版本
本篇文章中談到的所有安裝包資源,在公眾號【大數(shù)據(jù)夢想家】后臺回復 “presto”即可獲得!
1、將 yanagishima-20.0.zip 安裝包上傳至 linux121 服務(wù)器上 2、解壓 yanagishima-20.0.zip 安裝包
[root@node01 software]# unzip yanagishima-20.0.zip -d /export/servers/
3、.進入到 /opt/servers/yanagishima-20.0/conf/目錄下,修改 yanagishima.properties 配置文件
#指定 jetty 的端口,類似 tomcat 的 web 容器的一個組件
jetty.port=7788
#指定數(shù)據(jù)源
presto.datasources=presto_test
presto.coordinator.server.presto_test=http://node01:8080
catalog.presto_test=hive
schema.presto_test=ods
sql.query.engines=presto
4、啟動 yanagishima
[root@node01 yanagishima-20.0]# nohup bin/yanagishima-start.sh 1>/dev/null 2>&1 &
5、webUI訪問界面
通過http://node01:7788/,即可查詢到相關(guān)信息
6、查看 Presto 表結(jié)構(gòu),如下圖所示:

在“Treeview”頁面下可以查看所有表的結(jié)構(gòu),包括Schema,Table,Column等。
比如,執(zhí)行SELECT * FROM hive.company."action" LIMIT 100
每張表后面都有一個復制圖標,單擊此圖標可以復制完整的表名,然后在上面的文本框中輸入 SQL 語句 即可,如圖所示:
還可以查詢列表中其他的表格,比如,想要執(zhí)行現(xiàn)在已經(jīng)寫好了的SQL語句,SELECT * FROM hive.company."demo01" LIMIT 100,按Ctrl + Enter組合鍵顯示查詢結(jié)果,如圖所示:
當然,我們也可以通過Query List模塊查詢我們執(zhí)行過的SQL詳細信息,包括State,query ID,Elapsed,Query,Source,User....
更多使用,就不一一劇透介紹,小伙伴們可以自行去研究~
6、Presto的優(yōu)化
Presto 的優(yōu)化是一個非常有水平的問題,大致總結(jié)下,分如下幾個類別:
6.1 數(shù)據(jù)存儲
想要使用 Presto 更高效地查詢數(shù)據(jù),需要在數(shù)據(jù)存儲方面利用一些優(yōu)化手段。
6.1.1 合理設(shè)置分區(qū)
與 Hive 類似,Presto 會根據(jù)元數(shù)據(jù)信息讀取分區(qū)數(shù)據(jù),合理地設(shè)置分區(qū)能減少 Presto 數(shù)據(jù)讀取量,提升查詢性能。
6.1.2 使用 ORC 格式存儲
Presto 對 ORC文件 讀取進行了特定優(yōu)化,因此,在 Hive 中創(chuàng)建 Presto 使用的表時,建議采用 ORC 格式存儲。相對于 Parquet 格式,Presto 對 ORC 格式支持得更好。
6.1.3 使用壓縮
數(shù)據(jù)壓縮可以減少節(jié)點間數(shù)據(jù)傳輸對 IO 帶寬的壓力,對于即席查詢需要快速解壓,建議采用 Snappy壓縮。
6.1.4 預(yù)先排序
對于已經(jīng)排序的數(shù)據(jù),在查詢的數(shù)據(jù)過濾階段,ORC格式支持跳過讀取不必要的數(shù)據(jù)。比如對于經(jīng)常需要過濾的字段可以預(yù)先排序。
INSERT INTO table nation_orc partition(p) SELECT * FROM nation SORT BY n_name;
如果需要過濾 n_name 字段,則性能將提升。
SELECT count(*) FROM nation_orc WHERE n_name=’AUSTRALIA’;
6.2 SQL查詢
想要使用 Presto更高效地查詢數(shù)據(jù),需要在編寫查詢SQL語句方面利用一些優(yōu)化手段。
6.2.1 只選擇需要的字段
由于采用列式存儲,所以只選擇需要的字段可加快字段的讀取速度,減少數(shù)據(jù)量。避免采用 * 讀取所有字段。
[GOOD]: SELECT time,user,host FROM tbl
[BAD]: SELECT * FROM tbl
6.2.2 過濾條件必須加上分區(qū)字段
對于有分區(qū)的表,where語句中優(yōu)先使用分區(qū)字段進行過濾。acct_day 是分區(qū)字段,visit_time 是具體訪問時間。
[GOOD]: SELECT time,user,host FROM tbl where acct_day=20171101
[BAD]: SELECT * FROM tbl where visit_time=20171101
6.2.3 Group By語句優(yōu)化
合理安排 Group by語句中字段順序?qū)π阅苡幸欢ㄌ嵘?/strong>。將 Group By 語句中字段按照每個字段 distinct 數(shù)據(jù)多少進行降序排列。
[GOOD]: SELECT GROUP BY uid, gender
[BAD]: SELECT GROUP BY gender, uid
6.2.4 Order by時使用Limit
Order by 需要掃描數(shù)據(jù)到單個 worker 節(jié)點進行排序,導致單個worker需要大量內(nèi)存。如果是查詢 Top N 或者 Bottom N,使用 limit 可減少排序計算和內(nèi)存壓力。
[GOOD]: SELECT * FROM tbl ORDER BY time LIMIT 100
[BAD]: SELECT * FROM tbl ORDER BY time
6.2.5 使用近似聚合函數(shù)
Presto有一些近似聚合函數(shù),對于允許有少量誤差的查詢場景,使用這些函數(shù)對查詢性能有大幅提升。比如使用approx_distinct()函數(shù)比Count(distinct x)有大概2.3%的誤差。
SELECT approx_distinct(user_id) FROM access
6.2.6 用regexp_like代替多個like語句
Presto查詢優(yōu)化器沒有對多個 like 語句進行優(yōu)化,使用regexp_like對性能有較大提升。
[GOOD]
SELECT
...
FROM
access
WHERE
regexp_like(method, 'GET|POST|PUT|DELETE')
[BAD]
SELECT
...
FROM
access
WHERE
method LIKE '%GET%' OR
method LIKE '%POST%' OR
method LIKE '%PUT%' OR
method LIKE '%DELETE%'
6.2.7 使用Join語句時將大表放在左邊
Presto中 join 的默認算法是broadcast join,即將 join 左邊的表分割到多個 worker ,然后將join 右邊的表數(shù)據(jù)整個復制一份發(fā)送到每個worker進行計算。如果右邊的表數(shù)據(jù)量太大,則可能會報內(nèi)存溢出錯誤。
[GOOD] SELECT ... FROM large_table l join small_table s on l.id = s.id
[BAD] SELECT ... FROM small_table s join large_table l on l.id = s.id
6.2.8 使用Rank函數(shù)代替row_number函數(shù)來獲取Top N
在進行一些分組排序場景時,使用rank函數(shù)性能更好
[GOOD]
SELECT checksum(rnk)
FROM (
SELECT rank() OVER (PARTITION BY l_orderkey, l_partkey ORDER BY l_shipdate DESC) AS rnk
FROM lineitem
) t
WHERE rnk = 1
[BAD]
SELECT checksum(rnk)
FROM (
SELECT row_number() OVER (PARTITION BY l_orderkey, l_partkey ORDER BY l_shipdate DESC) AS rnk
FROM lineitem
) t
WHERE rnk = 1
6.3 注意事項
ORC和Parquet 都支持列式存儲,但是ORC對Presto支持更好(Parquet對Impala支持更好)
對于列式存儲而言,存儲文件為二進制的,對于經(jīng)常增刪字段的表,建議不要使用列式存儲(修改文件元數(shù)據(jù)代價大)。對比數(shù)據(jù)倉庫,dwd層建議不要使用ORC,而dm層則建議使用。
6.4 可能會踩的坑
使用 Presto 需要注意如下幾點:
引用:https://segmentfault.com/a/1190000013120454?utm_source=tag-newest
6.4.1 如何加快在Presto上的數(shù)據(jù)統(tǒng)計
很多的時候,在Presto上對數(shù)據(jù)庫跨庫查詢,例如Mysql數(shù)據(jù)庫。這個時候Presto的做法是從MySQL數(shù)據(jù)庫端拉取最基本的數(shù)據(jù),然后再去做進一步的處理,例如統(tǒng)計等聚合操作。
舉個例子:
SELECT count(id) FROM table_1 WHERE condition=1;
上面的SQL語句會分為3個步驟進行:
(1)Presto發(fā)起到Mysql數(shù)據(jù)庫進行查詢
SELECT id FROM table_1 WHERE condition=1;
(2)對結(jié)果進行count計算
(3)返回結(jié)果
所以說,對于Presto來說,其跨庫查詢的瓶頸是在數(shù)據(jù)拉取這個步驟。若要提高數(shù)據(jù)統(tǒng)計的速度,可考慮把 Mysql 中相關(guān)的數(shù)據(jù)表定期轉(zhuǎn)移到HDFS中,并轉(zhuǎn)存為高效的列式存儲格式ORC。
所以定時歸檔是一個很好的選擇,這里還要注意,在歸檔的時候我們要選擇一個歸檔字段,如果是按日歸檔,我們可以用日期作為這個字段的值,采用yyyyMMdd的形式,例如20180123.
一般創(chuàng)建歸檔數(shù)據(jù)庫的SQL語句如下:
CREATE TABLE IF NOT EXISTS table_1 (
id INTEGER,
........
partition_date INTEGER
)WITH ( format = 'ORC', partitioned_by = ARRAY['partition_date'] );
查看創(chuàng)建的庫結(jié)構(gòu):
SHOW CREATE TABLE table_1; /*Only Presto*/
帶有分區(qū)的表創(chuàng)建完成之后,每天只要更新分區(qū)字段partition_date就可以了,聰明的Presto 就能將數(shù)據(jù)放置到規(guī)劃好的分區(qū)了。
如果要查看一個數(shù)據(jù)表的分區(qū)字段是什么,可以下面的語句:
SHOW PARTITIONS FROM table_1 /*Only Presto*/
6.4.2 查詢條件中盡量帶上分區(qū)字段進行過濾
如果數(shù)據(jù)被規(guī)當?shù)?HDFS 中,并帶有分區(qū)字段。在每次查詢歸檔表的時候,要帶上分區(qū)字段作為過濾條件,這樣可以加快查詢速度。因為有了分區(qū)字段作為查詢條件,就能幫助Presto避免全區(qū)掃描,減少Presto需要掃描的HDFS的文件數(shù)。
6.4.3 多多使用 WITH 語句
使用 Presto 分析統(tǒng)計數(shù)據(jù)時,可考慮把多次查詢合并為一次查詢,用 Presto 提供的子查詢完成。
這點和我們熟知的MySQL的使用不是很一樣。
例如:
WITH subquery_1 AS (
SELECT a1, a2, a3
FROM Table_1
WHERE a3 between 20180101 and 20180131
), /*子查詢subquery_1,注意:多個子查詢需要用逗號分隔*/
subquery_2 AS (
SELECT b1, b2, b3
FROM Table_2
WHERE b3 between 20180101 and 20180131
) /*最后一個子查詢后不要帶逗號,不然會報錯。*/
SELECT
subquery_1.a1, subquery_1.a2,
subquery_2.b1, subquery_2.b2
FROM subquery_1
JOIN subquery_2
ON subquery_1.a3 = subquery_2.b3;
6.4.4 利用子查詢,減少讀表的次數(shù),尤其是大數(shù)據(jù)量的表
具體做法是,將使用頻繁的表作為一個子查詢抽離出來,避免多次 read。
6.4.5 只查詢需要的字段
一定要避免在查詢中使用 SELECT * 這樣的語句,就像只有告訴我們需要查詢數(shù)據(jù)越具體,工作效率越高。
對于我們的數(shù)據(jù)庫而言也是這樣,任務(wù)越明確,工作效率越高。
對于要查詢?nèi)孔侄蔚男枨笠彩沁@樣,沒有偷懶的捷徑,把它們都寫出來。
6.4.6 Join查詢優(yōu)化
Join左邊盡量放小數(shù)據(jù)量的表,而且最好是重復關(guān)聯(lián)鍵少的表。
6.4.7 字段名引用
避免字段名與關(guān)鍵字沖突:MySQL對于關(guān)鍵字沖突的字段名加反引號,Presto 對與關(guān)鍵字沖突的字段名加雙引號。當然,如果字段名不與關(guān)鍵字沖突,則可以不加雙引號。
6.4.8 時間函數(shù)
對于 timestamp,需要進行比較的時候,需要添加 timestamp 關(guān)鍵字,而 MySQL 中對 timestamp 可以直接進行比較。
/*MySQL的寫法*/
SELECT t FROM a WHERE t > '2017-01-01 00:00:00';
/*Presto中的寫法*/
SELECT t FROM a WHERE t > timestamp '2017-01-01 00:00:00';
6.4.9 MD5 函數(shù)的使用
Presto 中 MD5 函數(shù)傳入的 是 binary 類型,返回的也是binary類型,要對字符串進行 MD5操作時,需要轉(zhuǎn)換:
SELECT to_hex(md5(to_utf8('1212')));
6.4.10 不支持 INSERT OVERWRITE 語法
Presto中不支持 insert overwrite語法,只能先delete,然后insert into
6.4.11 ORC 格式
Presto 中對 ORC 文件格式進行了針對性優(yōu)化,但在 impala 中目前不支持ORC格式的表,hive中支持 ORC 格式的表,所以想用列式存儲的時候可以優(yōu)先考慮ORC格式
6.4.12 PARQUET 格式
Presto 目前支持 parquet 格式,支持查詢,但不支持 insert
巨人的肩膀
1、《大數(shù)據(jù)分析數(shù)據(jù)倉庫項目實戰(zhàn)》
2、《大數(shù)據(jù)技術(shù)實戰(zhàn)》
3、《大數(shù)據(jù)私房菜_Presto的安裝和使用》
4、 《impala與Presto的性能比較》https://blog.csdn.net/u012551524/article/details/79124532
5、《Presto踩坑指南》https://segmentfault.com/a/1190000013120454?utm_source=tag-newest
小結(jié)
本篇內(nèi)容為大家介紹的是關(guān)于從 0 到 1 學習 Presto 的過程,內(nèi)容算是比較的完整!包括從Presto的簡介,安裝部署,命令行 Client 的安裝,基本使用,可視化客戶端的安裝與基本使用,以及使用任何一個組件我們都很注重的優(yōu)化 ...... 希望大家看完之后能夠有所收獲!
