前言
團隊需要一個OLAP引擎,在對比了多種開源系統(tǒng)后,選擇了Presto。簡單總結下,以后可能會寫一些源碼解讀,二次開發(fā),問題與調優(yōu)的文章。
我們的需求是一個支持多種組件的統(tǒng)一SQL引擎,以及資源隊列,權限控制,SQL監(jiān)控管理等上層功能,性能當然越快越好。
Hive
太古老了,Hive3倒是添加了很多如LLAP,TEZ引擎優(yōu)化,更成熟的事務特性等,但是不方便支持第三方組件如ES,設計的StorageHandler擴展接口很蠢很死板,用它的MetaStore就可以了。。好像反正不管hive怎么優(yōu)化,都是被別人隨便10x性能PK的倒霉蛋。
Impala
這個重點是跑HDFS的Hive表(還有Hbase/Kudu)像其他組件支持的不多,并且元數(shù)據設計太重了,以前動則緩存整個表分區(qū)文件block等信息,還廣播到集群。不過最新4.x版本好像在改進這方面問題 也太慢了。。
Spark
作為批處理的業(yè)界老大,用了幾年SparkSQL,并不適合作為數(shù)據倉庫產品級的東西,沒有細粒度的權限控制(與Sentry/Ranger都不好集成 官方都不做),只做了檢索相關的SQL,沒有擴展性的權限/角色等定義,也沒有資源隔離,單點調度(當然正常情況下Presto也是,但是presto是流水線式調度的,task是迭代器模式,而Spark是一下子產生全部靜態(tài)集合的Task,即使limit 10,這樣元數(shù)據壓力極大)等等 很多地方 不適合作為一個大集群的對外JDBC出口。提供了DataSource擴展接口,第三方組件組要靠個人或者其他團隊支持(不是官方庫提供,總覺得質量無法保證)。因為本質上Spark作為批處理框架,不是作為數(shù)據庫去設計的。。雖然SparkSQL社區(qū)投入了巨大的力量去做DataSet統(tǒng)一優(yōu)化。??赡苣硞€單一語句SparkSQL性能勝出,但是作為整體功能性評估是不夠的。
像其他Druid,ClickHouse,Kylin,Greenplum要么是單一工具,要么擴展性不好,就不考慮了。。
Presto簡介
- 基于內存的并?計算,分布式SQL交互式查詢引擎(當然也支持Spill到Disk)
- Massively parallel processing (MPP)架構
- 多個節(jié)點管道式執(zhí)?,性能不輸SPARK,比hive快10倍+
- 由Coordinator和多個Worker組成
- 支持大量的組件,提供統(tǒng)一SQL入口,只需要配置即可【重點】
- 有豐富的數(shù)據庫特性:隊列、優(yōu)先級、權限、資源隔離、WEBUI、等
[官方團隊有個類似最佳實踐/cook-book的文檔] (https://trino.io/blog/2020/04/11/the-definitive-guide.html)
PS:當前版本 0.258支持的Connector有
Accumulo Connector // kv 類似hbase
BigQuery Connector
Black Hole Connector // 類似 /dev/null
Cassandra Connector
Druid Connector
Elasticsearch Connector // 重點使用
Hive Connector // 重點使用
Hive Security Configuration
Iceberg Connector
JMX Connector //好像也只是本集群的信息 。。
Kafka Connector
Kudu Connector
Local File Connector // 好像可以作為本地數(shù)據庫 ?
Memory Connector // 并不能持久化 。。
MongoDB Connector
MySQL Connector
Oracle Connector
Apache Pinot Connector
PostgreSQL Connector
Redis Connector
Redshift Connector
SQL Server Connector
System Connector // 本集群的信息
Thrift Connector
TPCDS Connector //快速構建數(shù)據集和測試
TPCH Connector
關于Presto與Trino
Trino是由原團隊由于與FaceBook管理層理念不一致,而開的新分支,社區(qū)分裂的細節(jié)不清楚,反正現(xiàn)在兩邊都在更新,社區(qū)也都很活躍,過了2年,具體的代碼區(qū)別已經非常大了,合并幾乎是不可能的事情。。
選Trino還是Presto糾結了許久,Trino畢竟是創(chuàng)始團隊支持的,并且好像現(xiàn)在支持的Connector數(shù)量更多,我個人兩邊代碼都下載瀏覽了一下,Trino的代碼組織和結構好看的多,性能對比沒有實測,但是看GitHub上兩邊的RoadMap與Blog來看,似乎Presto研發(fā)力量更強一些。。(只是個人感覺 歡迎討論)
PS:以Coordinator的HA為例
Trino社區(qū)在2019就提出了?!,F(xiàn)在依然沒有release

而Presto已經實現(xiàn)了,并且還有RaptorX這個分層緩存(在存算分離架構下有很好的性能提升)等,另外Presto這邊還計劃做Coordinator的負載均衡,和HA還不是一回事,這在大集群里需求挺強烈的。

[分層緩存介紹] (https://prestodb.io/blog/2021/02/04/raptorx)
來個presto的執(zhí)行圖(這類東西大同小異,與SparkSQL差不多也能對應)

Presto主要概念
Coordinator
對外負責管理集群與客戶端的連接,并接收客戶端查詢請求。
進行SQL的語法解析、查詢計劃生成和優(yōu)化,并進行查詢任務的調度。
集群的管理節(jié)點。內置了discovery server,跟蹤Worker節(jié)點的狀態(tài)
部署情況:一般作為單獨節(jié)點部署在集群中
通信方式:使用RESTful接口與客戶端、Workers進行交互
Worker
集群的工作節(jié)點。用于執(zhí)行被分解后的查詢任務(task)及處理數(shù)據
部署情況:一般集群中部署多個worker節(jié)點
通信方式:使用RESTful接口與Coordinator、其他Workers進行交互
數(shù)據源 Connector
Presto通過connector可以訪問多種不同的數(shù)據源。
connector相當于數(shù)據庫訪問的驅動。
每種connector通過實現(xiàn)Presto的SPI接口實現(xiàn)數(shù)據源的標準接入。
Catalog
Catalog可以包含多個schema,并且通過使用指定的connector訪問指定的數(shù)據源。例如,通過配置Hive catalog來訪問Hive數(shù)據源。
Schema
作用:用于管理表,類似于Mysql中的database。一個catalog及一個schema可以唯一確定一組可查詢的表集合。
Table
與傳統(tǒng)關系數(shù)據庫的概念類似。從數(shù)據源到表達映射由connector指定。
元數(shù)據結構圖

Presto查詢執(zhí)行模型
Statement
Presto支持ANSI標準的SQL語句,這些語句包括子句(caluses)、表達式(expressions)、斷言(predicates)組成。
Presto為什么要區(qū)分statement和query點概念呢?
在Presto中,statesments指的是用戶輸入的SQL語句的文本表示。
當statement被執(zhí)行時,Presto會創(chuàng)建查詢執(zhí)行及查詢計劃用于執(zhí)行相應query,
而查詢計劃是在一系列Worker節(jié)點上分布式執(zhí)行的。
【This is necessary because, in Presto,
statements simply refer to the textual representation of a SQL statement.
When a statement is executed,
Presto creates a query along with a query plan that is then distributed across a series of Presto workers.】
Query
當Presto接收到一個SQL語句(statement),
會將其轉換為一個查詢執(zhí)行(Query),同時創(chuàng)建查詢計劃(query plan)。
其中,查詢計劃是運行在Prestor Workers上的一系列相關聯(lián)的stages。
Statement 與 Query的差別:Statement是輸入給Presto的SQL文本;
Query是用于為了執(zhí)行Statement而實例化出來的一些列配置及組件。
一個Query包含stages、tasks、splits、connectors等組件和相應的數(shù)據源這些概念。
Stage
當Presto執(zhí)行Query時,會將query拆分成具有層次關系的多個stages。
例如,Presto從Hive中查詢1億條記錄并進行數(shù)據聚合時,
Presto會創(chuàng)建一系列的stages用于執(zhí)行相應的分布式查詢,
同時創(chuàng)建一個root stage用于聚合上述stages的查詢輸出,
之后將結果聚合后輸出給Coordinator,并進一步輸出給用戶。
一個Query的stages之間是樹形的層次結構。
每一個Query都有一個Root stage,用于聚合所有其他Stages的輸出數(shù)據。
Stage只是coordinator用于分布式查詢計劃(query plan)建模的邏輯概念,
本身并不會執(zhí)行在Presto Workers上。
Task
Presto是通過Task來運行的。
一個分布式查詢計劃(query plan)被拆解成一些列的stage。
一個stage分解成一系列并行執(zhí)行的task。
每個task被分解成一個或多個并行的driver,每個driver作用于一系列splist上。
每個task都有對應的輸入輸出。
Driver
一個Task包含一個或多個driver。
Drivers處理數(shù)據,并由task聚合后傳給下游stage的一個task。
一個Driver就是作用于一個split上的一系列operator的集合。
Driver是Presto架構最底層的并行處理單元。
每個driver都有一個輸入和一個輸出。
Operator
一個Operator代碼對于一個Split的一種操作。
一個Operator依次讀取一個Split中的數(shù)據,
將Operator所代表的計算和操作應用于該split上,并產生輸出。
如讀取表文件的Operatior。
Split
一個split是整個大的數(shù)據集上的一個小的切片。
位于分布式query plan中較低層次的stages從數(shù)據源獲取splits,
位于較高層次的中間stages則從其他stages取數(shù)據。
Exchange
Exchange用于不同Presto節(jié)點間的數(shù)據交換。
Task生產數(shù)據放入輸出緩存中,
也可以通過exchange客戶端從其他task消費數(shù)據。