==Presto實(shí)現(xiàn)原理和美團(tuán)的使用實(shí)踐 -

Presto實(shí)現(xiàn)原理和美團(tuán)的使用實(shí)踐 -
http://tech.meituan.com/presto.html

Facebook的數(shù)據(jù)倉(cāng)庫(kù)存儲(chǔ)在少量大型Hadoop/HDFS集群懂昂。Hive是Facebook在幾年前專為Hadoop打造的一款數(shù)據(jù)倉(cāng)庫(kù)工具戏自。在以前抵蚊,F(xiàn)acebook的科學(xué)家和分析師一直依靠Hive來(lái)做數(shù)據(jù)分析垢箕。但Hive使用MapReduce作為底層計(jì)算框架,是專為批處理設(shè)計(jì)的。但隨著數(shù)據(jù)越來(lái)越多,使用Hive進(jìn)行一個(gè)簡(jiǎn)單的數(shù)據(jù)查詢可能要花費(fèi)幾分到幾小時(shí),顯然不能滿足交互式查詢的需求渴析。Facebook也調(diào)研了其他比Hive更快的工具,但它們要么在功能有所限制要么就太簡(jiǎn)單吮龄,以至于無(wú)法操作Facebook龐大的數(shù)據(jù)倉(cāng)庫(kù)俭茧。
2012年開(kāi)始試用的一些外部項(xiàng)目都不合適,他們決定自己開(kāi)發(fā)漓帚,這就是Presto恢恼。2012年秋季開(kāi)始開(kāi)發(fā),目前該項(xiàng)目已經(jīng)在超過(guò) 1000名Facebook雇員中使用胰默,運(yùn)行超過(guò)30000個(gè)查詢场斑,每日數(shù)據(jù)在1PB級(jí)別。Facebook稱Presto的性能比Hive要好上10倍多牵署。2013年Facebook正式宣布開(kāi)源Presto漏隐。
本文首先介紹Presto從用戶提交SQL到執(zhí)行的這一個(gè)過(guò)程,然后嘗試對(duì)Presto實(shí)現(xiàn)實(shí)時(shí)查詢的原理進(jìn)行分析和總結(jié)奴迅,最后介紹Presto在美團(tuán)的使用情況青责。
Presto架構(gòu)


presto架構(gòu)圖

Presto查詢引擎是一個(gè)Master-Slave的架構(gòu),由一個(gè)Coordinator節(jié)點(diǎn)取具,一個(gè)Discovery Server節(jié)點(diǎn)脖隶,多個(gè)Worker節(jié)點(diǎn)組成,Discovery Server通常內(nèi)嵌于Coordinator節(jié)點(diǎn)中暇检。Coordinator負(fù)責(zé)解析SQL語(yǔ)句产阱,生成執(zhí)行計(jì)劃,分發(fā)執(zhí)行任務(wù)給Worker節(jié)點(diǎn)執(zhí)行块仆。Worker節(jié)點(diǎn)負(fù)責(zé)實(shí)際執(zhí)行查詢?nèi)蝿?wù)构蹬。Worker節(jié)點(diǎn)啟動(dòng)后向Discovery Server服務(wù)注冊(cè)王暗,Coordinator從Discovery Server獲得可以正常工作的Worker節(jié)點(diǎn)。如果配置了Hive Connector庄敛,需要配置一個(gè)Hive MetaStore服務(wù)為Presto提供Hive元信息俗壹,Worker節(jié)點(diǎn)與HDFS交互讀取數(shù)據(jù)。
Presto執(zhí)行查詢過(guò)程簡(jiǎn)介
既然Presto是一個(gè)交互式的查詢引擎藻烤,我們最關(guān)心的就是Presto實(shí)現(xiàn)低延時(shí)查詢的原理绷雏,我認(rèn)為主要是下面幾個(gè)關(guān)鍵點(diǎn),當(dāng)然還有一些傳統(tǒng)的SQL優(yōu)化原理怖亭,這里不介紹了之众。
完全基于內(nèi)存的并行計(jì)算
流水線
本地化計(jì)算
動(dòng)態(tài)編譯執(zhí)行計(jì)劃
小心使用內(nèi)存和數(shù)據(jù)結(jié)構(gòu)
類BlinkDB的近似查詢
GC控制

為了介紹上述幾個(gè)要點(diǎn),這里先介紹一下Presto執(zhí)行查詢的過(guò)程
提交查詢
用戶使用Presto Cli提交一個(gè)查詢語(yǔ)句后依许,Cli使用HTTP協(xié)議與Coordinator通信,Coordinator收到查詢請(qǐng)求后調(diào)用SqlParser解析SQL語(yǔ)句得到Statement對(duì)象缀蹄,并將Statement封裝成一個(gè)QueryStarter對(duì)象放入線程池中等待執(zhí)行峭跳。


提交查詢

SQL編譯過(guò)程
Presto與Hive一樣,使用Antlr編寫(xiě)SQL語(yǔ)法缺前,語(yǔ)法規(guī)則定義在Statement.g和StatementBuilder.g兩個(gè)文件中蛀醉。如下圖中所示從SQL編譯為最終的物理執(zhí)行計(jì)劃大概分為5部,最終生成在每個(gè)Worker節(jié)點(diǎn)上運(yùn)行的LocalExecutionPlan衅码,這里不詳細(xì)介紹SQL解析為邏輯執(zhí)行計(jì)劃的過(guò)程拯刁,通過(guò)一個(gè)SQL語(yǔ)句來(lái)理解查詢計(jì)劃生成之后的計(jì)算過(guò)程。


SQL解析過(guò)程

樣例SQL:
select c1.rank, count(*) from dim.city c1 join dim.city c2 on c1.id = c2.id where c1.id > 10 group by c1.rank limit 10;
邏輯執(zhí)行計(jì)劃

上面的SQL語(yǔ)句生成的邏輯執(zhí)行計(jì)劃Plan如上圖所示逝段。那么Presto是如何對(duì)上面的邏輯執(zhí)行計(jì)劃進(jìn)行拆分以較高的并行度去執(zhí)行完這個(gè)計(jì)劃呢垛玻,我們來(lái)看看物理執(zhí)行計(jì)劃。
物理執(zhí)行計(jì)劃
邏輯執(zhí)行計(jì)劃圖中的虛線就是Presto對(duì)邏輯執(zhí)行計(jì)劃的切分點(diǎn)奶躯,邏輯計(jì)劃Plan生成的SubPlan分為四個(gè)部分帚桩,每一個(gè)SubPlan都會(huì)提交到一個(gè)或者多個(gè)Worker節(jié)點(diǎn)上執(zhí)行。
SubPlan有幾個(gè)重要的屬性planDistribution嘹黔、outputPartitioning账嚎、partitionBy屬性郭蕉。
PlanDistribution表示一個(gè)查詢Stage的分發(fā)方式召锈,邏輯執(zhí)行計(jì)劃圖中的4個(gè)SubPlan共有3種不同的PlanDistribution方式:Source表示這個(gè)SubPlan是數(shù)據(jù)源规求,Source類型的任務(wù)會(huì)按照數(shù)據(jù)源大小確定分配多少個(gè)節(jié)點(diǎn)進(jìn)行執(zhí)行;Fixed表示這個(gè)SubPlan會(huì)分配固定的節(jié)點(diǎn)數(shù)進(jìn)行執(zhí)行(Config配置中的query.initial-hash-partitions參數(shù)配置丛塌,默認(rèn)是8)赴邻;None表示這個(gè)SubPlan只分配到一個(gè)節(jié)點(diǎn)進(jìn)行執(zhí)行。在下面的執(zhí)行計(jì)劃中彤敛,SubPlan1和SubPlan0 PlanDistribution=Source,這兩個(gè)SubPlan都是提供數(shù)據(jù)源的節(jié)點(diǎn)袄秩,SubPlan1所有節(jié)點(diǎn)的讀取數(shù)據(jù)都會(huì)發(fā)向SubPlan0的每一個(gè)節(jié)點(diǎn);SubPlan2分配8個(gè)節(jié)點(diǎn)執(zhí)行最終的聚合操作猪狈;SubPlan3只負(fù)責(zé)輸出最后計(jì)算完成的數(shù)據(jù)。
OutputPartitioning屬性只有兩個(gè)值HASH和NONE疆前,表示這個(gè)SubPlan的輸出是否按照partitionBy的key值對(duì)數(shù)據(jù)進(jìn)行Shuffle。在下面的執(zhí)行計(jì)劃中只有SubPlan0的OutputPartitioning=HASH书释,所以SubPlan2接收到的數(shù)據(jù)是按照rank字段Partition后的數(shù)據(jù)。

物理執(zhí)行計(jì)劃

完全基于內(nèi)存的并行計(jì)算
查詢的并行執(zhí)行流程
Presto SQL的執(zhí)行流程如下圖所示
Cli通過(guò)HTTP協(xié)議提交SQL查詢之后,查詢請(qǐng)求封裝成一個(gè)SqlQueryExecution對(duì)象交給Coordinator的SqlQueryManager#queryExecutor線程池去執(zhí)行
每個(gè)SqlQueryExecution線程(圖中Q-X線程)啟動(dòng)后對(duì)查詢請(qǐng)求的SQL進(jìn)行語(yǔ)法解析和優(yōu)化并最終生成多個(gè)Stage的SqlStageExecution任務(wù)熄阻,每個(gè)SqlStageExecution任務(wù)仍然交給同樣的線程池去執(zhí)行
每個(gè)SqlStageExecution線程(圖中S-X線程)啟動(dòng)后每個(gè)Stage的任務(wù)按PlanDistribution屬性構(gòu)造一個(gè)或者多個(gè)RemoteTask通過(guò)HTTP協(xié)議分配給遠(yuǎn)端的Worker節(jié)點(diǎn)執(zhí)行
Worker節(jié)點(diǎn)接收到RemoteTask請(qǐng)求之后,啟動(dòng)一個(gè)SqlTaskExecution線程(圖中T-X線程)將這個(gè)任務(wù)的每個(gè)Split包裝成一個(gè)PrioritizedSplitRunner任務(wù)(圖中SR-X)交給Worker節(jié)點(diǎn)的TaskExecutor#executor線程池去執(zhí)行

查詢執(zhí)行流程

上面的執(zhí)行計(jì)劃實(shí)際執(zhí)行效果如下圖所示。
Coordinator通過(guò)HTTP協(xié)議調(diào)用Worker節(jié)點(diǎn)的 /v1/task 接口將執(zhí)行計(jì)劃分配給所有Worker節(jié)點(diǎn)(圖中藍(lán)色箭頭)
SubPlan1的每個(gè)節(jié)點(diǎn)讀取一個(gè)Split的數(shù)據(jù)并過(guò)濾后將數(shù)據(jù)分發(fā)給每個(gè)SubPlan0節(jié)點(diǎn)進(jìn)行Join操作和Partial Aggr操作
SubPlan1的每個(gè)節(jié)點(diǎn)計(jì)算完成后按GroupBy Key的Hash值將數(shù)據(jù)分發(fā)到不同的SubPlan2節(jié)點(diǎn)
所有SubPlan2節(jié)點(diǎn)計(jì)算完成后將數(shù)據(jù)分發(fā)到SubPlan3節(jié)點(diǎn)
SubPlan3節(jié)點(diǎn)計(jì)算完成后通知Coordinator結(jié)束查詢畦木,并將數(shù)據(jù)發(fā)送給Coordinator

執(zhí)行計(jì)劃計(jì)算流程

源數(shù)據(jù)的并行讀取
在上面的執(zhí)行計(jì)劃中SubPlan1和SubPlan0都是Source節(jié)點(diǎn),其實(shí)它們讀取HDFS文件數(shù)據(jù)的方式就是調(diào)用的HDFS InputSplit API惨篱,然后每個(gè)InputSplit分配一個(gè)Worker節(jié)點(diǎn)去執(zhí)行,每個(gè)Worker節(jié)點(diǎn)分配的InputSplit數(shù)目上限是參數(shù)可配置的簿寂,Config中的query.max-pending-splits-per-node參數(shù)配置,默認(rèn)是100克胳。
分布式的Hash聚合
上面的執(zhí)行計(jì)劃在SubPlan0中會(huì)進(jìn)行一次Partial的聚合計(jì)算,計(jì)算每個(gè)Worker節(jié)點(diǎn)讀取的部分?jǐn)?shù)據(jù)的部分聚合結(jié)果腹忽,然后SubPlan0的輸出會(huì)按照group by字段的Hash值分配不同的計(jì)算節(jié)點(diǎn),最后SubPlan3合并所有結(jié)果并輸出
流水線
數(shù)據(jù)模型
Presto中處理的最小數(shù)據(jù)單元是一個(gè)Page對(duì)象着裹,Page對(duì)象的數(shù)據(jù)結(jié)構(gòu)如下圖所示。一個(gè)Page對(duì)象包含多個(gè)Block對(duì)象,每個(gè)Block對(duì)象是一個(gè)字節(jié)數(shù)組稍走,存儲(chǔ)一個(gè)字段的若干行。多個(gè)Block橫切的一行是真實(shí)的一行數(shù)據(jù)。一個(gè)Page最大1MB抑钟,最多16*1024行數(shù)據(jù)。


數(shù)據(jù)模型

節(jié)點(diǎn)內(nèi)部流水線計(jì)算
下圖是一個(gè)Worker節(jié)點(diǎn)內(nèi)部的計(jì)算流程圖,左側(cè)是任務(wù)的執(zhí)行流程圖揪利。
Worker節(jié)點(diǎn)將最細(xì)粒度的任務(wù)封裝成一個(gè)PrioritizedSplitRunner對(duì)象喘垂,放入pending split優(yōu)先級(jí)隊(duì)列中得院。每個(gè)
Worker節(jié)點(diǎn)啟動(dòng)一定數(shù)目的線程進(jìn)行計(jì)算鸭限,線程數(shù)task.shard.max-threads=availableProcessors() * 4兜喻,在config中配置。
每個(gè)空閑的線程從隊(duì)列中取出一個(gè)PrioritizedSplitRunner對(duì)象執(zhí)行渡冻,如果執(zhí)行完成一個(gè)周期,超過(guò)最大執(zhí)行時(shí)間1秒鐘,判斷任務(wù)是否執(zhí)行完成脆荷,如果完成,從allSplits隊(duì)列中刪除,如果沒(méi)有,則放回pendingSplits隊(duì)列中七兜。
每個(gè)任務(wù)的執(zhí)行流程如下圖右側(cè)惜犀,依次遍歷所有Operator莉御,嘗試從上一個(gè)Operator取一個(gè)Page對(duì)象迄薄,如果取得的Page不為空冶伞,交給下一個(gè)Operator執(zhí)行。


節(jié)點(diǎn)內(nèi)部流水線計(jì)算

節(jié)點(diǎn)間流水線計(jì)算
下圖是ExchangeOperator的執(zhí)行流程圖铺董,ExchangeOperator為每一個(gè)Split啟動(dòng)一個(gè)HttpPageBufferClient對(duì)象,主動(dòng)向上一個(gè)Stage的Worker節(jié)點(diǎn)拉數(shù)據(jù)粹懒,數(shù)據(jù)的最小單位也是一個(gè)Page對(duì)象重付,取到數(shù)據(jù)后放入Pages隊(duì)列中
節(jié)點(diǎn)間流水線計(jì)算

本地化計(jì)算
Presto在選擇Source任務(wù)計(jì)算節(jié)點(diǎn)的時(shí)候,對(duì)于每一個(gè)Split凫乖,按下面的策略選擇一些minCandidates
優(yōu)先選擇與Split同一個(gè)Host的Worker節(jié)點(diǎn)
如果節(jié)點(diǎn)不夠優(yōu)先選擇與Split同一個(gè)Rack的Worker節(jié)點(diǎn)
如果節(jié)點(diǎn)還不夠隨機(jī)選擇其他Rack的節(jié)點(diǎn)

對(duì)于所有Candidate節(jié)點(diǎn)确垫,選擇assignedSplits最少的節(jié)點(diǎn)。
動(dòng)態(tài)編譯執(zhí)行計(jì)劃
Presto會(huì)將執(zhí)行計(jì)劃中的ScanFilterAndProjectOperator和FilterAndProjectOperator動(dòng)態(tài)編譯為Byte Code帽芽,并交給JIT去編譯為native代碼删掀。Presto也使用了Google Guava提供的LoadingCache緩存生成的Byte Code。

動(dòng)態(tài)編譯執(zhí)行計(jì)劃

動(dòng)態(tài)編譯執(zhí)行計(jì)劃

上面的兩段代碼片段中导街,第一段為沒(méi)有動(dòng)態(tài)編譯前的代碼披泪,第二段代碼為動(dòng)態(tài)編譯生成的Byte Code反編譯之后還原的優(yōu)化代碼,我們看到這里采用了循環(huán)展開(kāi)的優(yōu)化方法搬瑰。
循環(huán)展開(kāi)最常用來(lái)降低循環(huán)開(kāi)銷款票,為具有多個(gè)功能單元的處理器提供指令級(jí)并行。也有利于指令流水線的調(diào)度泽论。
小心使用內(nèi)存和數(shù)據(jù)結(jié)構(gòu)
使用Slice進(jìn)行內(nèi)存操作艾少,Slice使用Unsafe#copyMemory實(shí)現(xiàn)了高效的內(nèi)存拷貝,Slice倉(cāng)庫(kù)參考:https://github.com/airlift/slice
Facebook工程師在另一篇介紹ORCFile優(yōu)化的文章中也提到使用Slice將ORCFile的寫(xiě)性能提高了20%~30%翼悴,參考:https://code.facebook.com/posts/229861827208629/scaling-the-facebook-data-warehouse-to-300-pb/
類BlinkDB的近似查詢
為了加快avg缚够、count distinct、percentile等聚合函數(shù)的查詢速度抄瓦,Presto團(tuán)隊(duì)與BlinkDB作者之一Sameer Agarwal合作引入了一些近似查詢函數(shù)approx_avg潮瓶、approx_distinct陶冷、approx_percentile钙姊。approx_distinct使用HyperLogLog Counting算法實(shí)現(xiàn)。
GC控制
Presto團(tuán)隊(duì)在使用hotspot java7時(shí)發(fā)現(xiàn)了一個(gè)JIT的BUG埂伦,當(dāng)代碼緩存快要達(dá)到上限時(shí)煞额,JIT可能會(huì)停止工作,從而無(wú)法將使用頻率高的代碼動(dòng)態(tài)編譯為native代碼。
Presto團(tuán)隊(duì)使用了一個(gè)比較Hack的方法去解決這個(gè)問(wèn)題膊毁,增加一個(gè)線程在代碼緩存達(dá)到70%以上時(shí)進(jìn)行顯式GC胀莹,使得已經(jīng)加載的Class從perm中移除,避免JIT無(wú)法正常工作的BUG婚温。
Presto TPCH benchmark測(cè)試
介紹了上述這么多點(diǎn)描焰,我們最關(guān)心的還是Presto性能測(cè)試,Presto中實(shí)現(xiàn)了TPCH的標(biāo)準(zhǔn)測(cè)試栅螟,下面的表格給出了Presto 0.60 TPCH的測(cè)試結(jié)果荆秦。直接運(yùn)行presto-main/src/test/java/com/facebook/presto/benchmark/BenchmarkSuite.java。
benchmarkName cpuNanos(MILLISECONDS) inputRows inputBytes inputRows/s inputBytes/s outputRows outputBytes outputRows/s outputBytes/s count_agg 2.055ms 1.5M 12.9MB 730M/s 6.12GB/s 1 9B 486/s 4.28KB/s double_sum_agg 14.792ms 1.5M 12.9MB 101M/s 870MB/s 1 9B 67/s 608B/s hash_agg 174.576ms 1.5M 21.5MB 8.59M/s 123MB/s 3 45B 17/s 257B/s predicate_filter 68.387ms 1.5M 12.9MB 21.9M/s 188MB/s 1.29M 11.1MB 18.8M/s 162MB/s raw_stream 1.899ms 1.5M 12.9MB 790M/s 6.62GB/s 1.5M 12.9MB 790M/s 6.62GB/s top100 58.735ms 1.5M 12.9MB 25.5M/s 219MB/s 100 900B 1.7K/s 15KB/s in_memory_orderby_1.5M 1909.524ms 1.5M 41.5MB 786K/s 21.7MB/s 1.5M 28.6MB 786K/s 15MB/s hash_build 588.471ms 1.5M 25.7MB 2.55M/s 43.8MB/s 1.5M 25.7MB 2.55M/s 43.8MB/s hash_join 2400.006ms 6M 103MB 2.5M/s 42.9MB/s 6M 206MB 2.5M/s 85.8MB/s hash_build_and_join 2996.489ms 7.5M 129MB 2.5M/s 43MB/s 6M 206MB 2M/s 68.8MB/s hand_tpch_query_1 3146.931ms 6M 361MB 1.91M/s 115MB/s 4 300B 1/s 95B/s hand_tpch_query_6 345.960ms 6M 240MB 17.3M/s 695MB/s 1 9B 2/s 26B/ssql_groupby_agg_with_arithmetic 1211.444ms 6M 137MB 4.95M/s 113MB/s 2 30B 1/s 24B/s sql_count_agg 3.635ms 1.5M 12.9MB 413M/s 3.46GB/s 1 9B 275/s 2.42KB/s sql_double_sum_agg 16.960ms 1.5M 12.9MB 88.4M/s 759MB/s 1 9B 58/s 530B/s sql_count_with_filter 81.641ms 1.5M 8.58MB 18.4M/s 105MB/s 1 9B 12/s 110B/s sql_groupby_agg 169.748ms 1.5M 21.5MB 8.84M/s 126MB/s 3 45B 17/s 265B/s sql_predicate_filter 46.540ms 1.5M 12.9MB 32.2M/s 277MB/s 1.29M 11.1MB 27.7M/s 238MB/s sql_raw_stream 3.374ms 1.5M 12.9MB 445M/s 3.73GB/s 1.5M 12.9MB 445M/s 3.73GB/s sql_top_100 60.663ms 1.5M 12.9MB 24.7M/s 212MB/s 100 900B 1.65K/s 14.5KB/s sql_hash_join 4421.159ms 7.5M 129MB 1.7M/s 29.1MB/s 6M 206MB 1.36M/s 46.6MB/s sql_join_with_predicate 1008.909ms 7.5M 116MB 7.43M/s 115MB/s 1 9B 0/s 8B/s sql_varbinary_max 224.510ms 6M 97.3MB 26.7M/s 433MB/s 1 21B 4/s 93B/s sql_distinct_multi 257.958ms 1.5M 32MB 5.81M/s 124MB/s 5 112B 19/s 434B/s sql_distinct_single 112.849ms 1.5M 12.9MB 13.3M/s 114MB/s 1 9B 8/s 79B/s sql_tpch_query_1 3168.782ms 6M 361MB 1.89M/s 114MB/s 4 336B 1/s 106B/s sql_tpch_query_6 286.281ms 6M 240MB 21M/s 840MB/s 1 9B 3/s 31B/s sql_like 3497.154ms 6M 232MB 1.72M/s 66.3MB/s 1.15M 9.84MB 328K/s 2.81MB/s sql_in 80.267ms 6M 51.5MB 74.8M/s 642MB/s 25 225B 311/s 2.74KB/s sql_semijoin_in 1945.074ms 7.5M 64.4MB 3.86M/s 33.1MB/s 3M 25.8MB 1.54M/s 13.2MB/s sql_regexp_like 2233.004ms 1.5M 76.6MB 672K/s 34.3MB/s 1 9B 0/s 4B/s sql_approx_percentile_long 587.748ms 1.5M 12.9MB 2.55M/s 21.9MB/s 1 9B 1/s 15B/s sql_between_long 53.433ms 1.5M 12.9MB 28.1M/s 241MB/s 1 9B 18/s 168B/ssampled_sql_groupby_agg_with_arithmetic 1369.485ms 6M 189MB 4.38M/s 138MB/s 2 30B 1/s 21B/s sampled_sql_count_agg 11.367ms 1.5M 12.9MB 132M/s 1.11GB/s 1 9B 87/s 791B/ssampled_sql_join_with_predicate 1338.238ms 7.5M 180MB 5.61M/s 135MB/s 1 9B 0/s 6B/s sampled_sql_double_sum_agg 24.638ms 1.5M 25.7MB 60.9M/s 1.02GB/s 1 9B 40/s 365B/s stat_long_variance 26.390ms 1.5M 12.9MB 56.8M/s 488MB/s 1 9B 37/s 341B/s stat_long_variance_pop 26.583ms 1.5M 12.9MB 56.4M/s 484MB/s 1 9B 37/s 338B/s stat_double_variance 26.601ms 1.5M 12.9MB 56.4M/s 484MB/s 1 9B 37/s 338B/s stat_double_variance_pop 26.371ms 1.5M 12.9MB 56.9M/s 488MB/s 1 9B 37/s 341B/s stat_long_stddev 26.266ms 1.5M 12.9MB 57.1M/s 490MB/s 1 9B 38/s 342B/s stat_long_stddev_pop 26.350ms 1.5M 12.9MB 56.9M/s 489MB/s 1 9B 37/s 341B/s stat_double_stddev 26.316ms 1.5M 12.9MB 57M/s 489MB/s 1 9B 38/s 342B/s stat_double_stddev_pop 26.360ms 1.5M 12.9MB 56.9M/s 488MB/s 1 9B 37/s 341B/s sql_approx_count_distinct_long 35.763ms 1.5M 12.9MB 41.9M/s 360MB/s 1 9B 27/s 251B/ssql_approx_count_distinct_double 37.198ms 1.5M 12.9MB 40.3M/s 346MB/s 1 9B 26/s 241B/s

美團(tuán)如何使用Presto
選擇presto的原因
2013年我們也用過(guò)一段時(shí)間的impala力图,當(dāng)時(shí)impala不支持線上1.x的hadoop社區(qū)版步绸,所以搭了一個(gè)CDH的小集群,每天將大集群的熱點(diǎn)數(shù)據(jù)導(dǎo)入小集群吃媒。但是hadoop集群年前完成升級(jí)2.2之后瓤介,當(dāng)時(shí)的impala還不支持2.2 hadoop版本。而Presto剛好開(kāi)始支持2.x hadoop社區(qū)版赘那,并且Presto在Facebook 300PB大數(shù)據(jù)量的環(huán)境下可以成功的得到大量使用刑桑,我們相信它在美團(tuán)也可以很好的支撐我們實(shí)時(shí)分析的需求,于是決定先上線測(cè)試使用一段時(shí)間募舟。
部署和使用形式
考慮到兩個(gè)原因:1漾月、由于Hadoop集群主要是夜間完成昨天的計(jì)算任務(wù),白天除了日志寫(xiě)入外胃珍,集群的計(jì)算負(fù)載較低梁肿。2、Presto Worker節(jié)點(diǎn)與DataNode節(jié)點(diǎn)布置在一臺(tái)機(jī)器上可以本地計(jì)算觅彰。因此我們將Presto部署到了所有的DataNode機(jī)器上吩蔑,并且夜間停止Presto服務(wù),避免占用集群資源填抬,夜間基本也不會(huì)有用戶查詢數(shù)據(jù)烛芬。
Presto二次開(kāi)發(fā)和BUG修復(fù)
年后才正式上線Presto查詢引擎,0.60版本飒责,使用的時(shí)間不長(zhǎng)赘娄,但是也遇到了一些問(wèn)題:
美團(tuán)的Hadoop使用的是2.2版本,并且開(kāi)啟了Security模式宏蛉,但是Presto不支持Kerberos認(rèn)證遣臼,我們修改了Presto代碼,增加了Kerberos認(rèn)證的功能拾并。
Presto還不支持SQL的隱式類型轉(zhuǎn)換揍堰,而Hive支持鹏浅,很多自助查詢的用戶習(xí)慣了Hive,導(dǎo)致使用Presto時(shí)都會(huì)出現(xiàn)表達(dá)式中左右變量類型不匹配的問(wèn)題屏歹,我們?cè)黾恿穗[式類型轉(zhuǎn)換的功能隐砸,大大減小了用戶SQL出錯(cuò)的概率。
Presto不支持查詢lzo壓縮的數(shù)據(jù)蝙眶,需要修改hadoop-lzo的代碼季希。
解決了一個(gè)having子句中有distinct字段時(shí)查詢失敗的BUG,并反饋了Presto團(tuán)隊(duì) https://github.com/facebook/presto/pull/1104

所有代碼的修改可以參考我們?cè)趃ithub上的倉(cāng)庫(kù) https://github.com/MTDATA/presto/commits/mt-0.60
實(shí)際使用效果
這里給出一個(gè)公司內(nèi)部開(kāi)放給分析師幽纷、PM胖眷、工程師進(jìn)行自助查詢的查詢中心的一個(gè)測(cè)試報(bào)告。這里選取了平時(shí)的5000個(gè)Hive查詢霹崎,通過(guò)Presto查詢的對(duì)比見(jiàn)下面的表格珊搀。
自助查詢sql數(shù)

hive

presto

presto/hive

1424
154427s
27708s
0.179424582489

參考
Presto官方文檔 http://prestodb.io/

Facebook Presto團(tuán)隊(duì)介紹Presto的文章https://www.facebook.com/notes/facebook-engineering/presto-interacting-with-petabytes-of-data-at-facebook/10151786197628920

SlideShare兩個(gè)分享Presto 的PPThttp://www.slideshare.net/zhusx/presto-overview?from_search=1http://www.slideshare.net/frsyuki/hadoop-source-code-reading-15-in-japan-presto

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市尾菇,隨后出現(xiàn)的幾起案子境析,更是在濱河造成了極大的恐慌,老刑警劉巖派诬,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劳淆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡默赂,警方通過(guò)查閱死者的電腦和手機(jī)沛鸵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)缆八,“玉大人曲掰,你說(shuō)我怎么就攤上這事∧纬剑” “怎么了栏妖?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)奖恰。 經(jīng)常有香客問(wèn)我吊趾,道長(zhǎng),這世上最難降的妖魔是什么瑟啃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任论泛,我火速辦了婚禮,結(jié)果婚禮上蛹屿,老公的妹妹穿的比我還像新娘屁奏。我一直安慰自己,他們只是感情好蜡峰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布了袁。 她就那樣靜靜地躺著,像睡著了一般湿颅。 火紅的嫁衣襯著肌膚如雪载绿。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天油航,我揣著相機(jī)與錄音崭庸,去河邊找鬼。 笑死谊囚,一個(gè)胖子當(dāng)著我的面吹牛怕享,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镰踏,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼函筋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了奠伪?” 一聲冷哼從身側(cè)響起跌帐,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绊率,沒(méi)想到半個(gè)月后谨敛,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滤否,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年脸狸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藐俺。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡炊甲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欲芹,到底是詐尸還是另有隱情蜜葱,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布耀石,位于F島的核電站牵囤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏滞伟。R本人自食惡果不足惜揭鳞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望梆奈。 院中可真熱鬧野崇,春花似錦、人聲如沸亩钟。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至扶镀,卻和暖如春蕴侣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背臭觉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工昆雀, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蝠筑。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓狞膘,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親什乙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子挽封,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容