1. 程式人生 > 資料庫 >2020-12-03《Presto分散式SQL查詢引擎——kkb筆記複習》

2020-12-03《Presto分散式SQL查詢引擎——kkb筆記複習》

Presto分散式SQL查詢引擎

一、課前準備

  1. jdk版本要求:Java 8 Update 151 or higher (8u151+), 64-bit

  2. 安裝好hadoop叢集

  3. 安裝好hive

二、課堂主題

  1. 介紹presto

  2. presto架構

  3. prsto安裝部署

  4. presto使用

三、課堂目標

  1. 理解presto

  2. 獨立完成presto安裝部署

  3. 使用presto

 

四、知識要點

1. Presto是什麼?

  • Hadoop提供了大資料儲存與計算的一整套解決方案;但是它採用的是MapReduce計算框架,只適合離線和批量計算,無法滿足快速實時的Ad-Hoc查詢計算的效能要求

  • Hive使用MapReduce作為底層計算框架,是專為批處理設計的。但隨著資料越來越多,使用Hive進行一個簡單的資料查詢可能要花費幾分到幾小時,顯然不能滿足互動式查詢的需求。

  • Facebook於2012年秋開始開發了Presto,每日查詢資料量在1PB級別。Facebook稱Presto的效能比Hive要快上10倍多。2013年Facebook正式宣佈開源Presto。

  • Presto是apache下開源的==OLAP的分散式SQL查詢引擎==,資料量支援從GB到PB級別的資料量的查詢,並且查詢時,能做到秒級查詢。

  • 另外,Presto雖然可以解析SQL,但它並非是標準的資料庫;不能替代如MySQL、PostgreSQL、Oracle關係型資料庫,不是用於處理OLTP的

  • presto是利用分散式查詢,高效的對海量資料進行查詢;

  • presto可以用來查詢hdfs上的海量資料;但是,presto不僅僅可以用來查詢hdfs的資料,它還被設計成能夠對很多其他的資料來源的資料做查詢;

  • 比如資料來源有HDFS、Hive、Druid、Kafka、kudu、MySQL、Redis等;下圖是Presto 0.237支援的資料來源

  •  

2. Presto架構

 

  • Presto查詢引擎是一個Master-Slave的架構,Coordinator是主,worker是從;

  • 一個presto叢集,由一個Coordinator節點,一個Discovery Server節點(通常內嵌於Coordinator節點中),多個Worker節點組成

    • Coordinator負責接收查詢請求、解析SQL語句、生成執行計劃、任務排程給Worker節點執行、worker管理。

    • Worker節點是工作節點;負責實際執行查詢任務Task;Worker節點啟動後向Discovery Server服務註冊;Coordinator從Discovery Server獲得可以正常工作的Worker節點。

  • Presto CLI提交查詢到Coordinator

  • catalog表示資料來源;每個catalog包含Connector及Schema

    • 其中Connector是資料來源的介面卡;presto通過Connector與不同的資料來源(如Redis、Hive、Kafka)連線;如果配置了Hive Connector,需要配置一個Hive MetaStore服務為Presto提供Hive元資訊,Worker節點與HDFS互動讀取資料。

    • Schema類似於MySQL中的資料庫的概念;Schema中又包含Table,類似於MySQL中的表

 

3. Presto特點

1. 優點

  • 高效能:Presto基於記憶體計算,減少資料的落盤,計算更快;輕量快速,支援近乎實時的查詢

  • 多資料來源:通過配置不同的Connector,presto可以連線不同的資料來源,所以可以將來自不同資料來源的表進行連線查詢

  • 支援SQL:完全支援ANSI SQL,並提供了sql shell命令列工具

  • 擴充套件性:可以根據實際的需要,開發特定的資料來源的Connector,從而可以sql查詢此資料元的資料

2. 缺點

  • 雖然Presto是基於記憶體做計算;但是資料量大時,資料並非全部儲存在記憶體中;

    • 比如Presto可針對PB級別的資料做計算,但Presto並非將所有資料全部儲存在記憶體中,不同場景有不同做法;

    • 比如count, avg等聚合運算,會讀部分資料,計算,在清理記憶體;再讀資料再計算、清理記憶體;所以佔據記憶體並不是很高;

    • 但是如果做join操作,中間可能會產生大量的臨時資料,造成執行速度變慢;join時,hive的資料反而更快些。所以如果join的話,建議在hive中,先進行join生成寬表,再使用presto查詢此寬表資料

3. presto與impala對比

  • impala效能比presto稍好

  • 但是,impala只能對接hive;而presto能對接很多種類的資料來源

 

4. 安裝部署Presto

官網地址:

presto叢集規劃

主機名角色
node01coordinator
node02worker
node03worker

1. 安裝部署Presto Server

  • presto要求

  •  

 

  • 確認python版本是2.4+

  •  

 

  • 確認java版本是8u151+;若如下圖,是151之前的版本,安裝presto時,需要特殊處理

  •  

1. 下載安裝包

然後將tar.gz包上傳到node01的/kkb/soft目錄

2. 解壓

cd /kkb/soft/
tar -xzvf presto-server-0.237.tar.gz -C /kkb/install/

3. 配置JAVA

  • 若java版本低於8u151,那麼需要上傳8u151+的版本壓縮包到/kkb/soft;若不低於,則跳過此步驟

  • 解壓

cd /kkb/soft/
tar -xzvf jdk-8u251-linux-x64.tar.gz -C /kkb/install/
cd /kkb/install/
scp -r jdk1.8.0_251/ node02:$PWD
scp -r jdk1.8.0_251/ node03:$PWD
  • 指定presto使用的java版本(3個節點都要修改)

ln -s presto-server-0.237/ presto
vim /kkb/install/presto/bin/launcher

新增如下內容

PATH=/kkb/install/jdk1.8.0_251/bin:$PATH
java -version

注意:需要加在exec "$(dirname "$0")/launcher.py" "$@"之前

 

3. 建立相關目錄

  • 建立儲存資料資料夾;presto將儲存log及其他資料到此目錄

cd /kkb/install
cd presto
mkdir data
  • 建立儲存配置檔案的資料夾

<span style="color:#333333">mkdir etc</span>

4. 新增JVM配置檔案

  • etc目錄下新增jvm.config配置檔案

cd /kkb/install/presto/etc
vim jvm.config
  • 內容如下

-server
-Xmx16G
-XX:+UseG1GC
-XX:G1HeapRegionSize=32M
-XX:+UseGCOverheadLimit
-XX:+ExplicitGCInvokesConcurrent
-XX:+HeapDumpOnOutOfMemoryError
-XX:+ExitOnOutOfMemoryError</span>

5. 配置資料來源

presto支援不同的資料來源,通過catalog進行配置;不同的資料來源,有不同的catalog

  • 現以hive資料來源為例,建立個hive的catalog

  • etc中建立目錄catalog

cd /kkb/install/presto-server-0.237/etc
mkdir catalog
cd catalog
vim hive.properties
  • 新增如下內容 注:因編輯問題凡遇到<span style="color:#333333"> 、</span>自動忽略

<span style="color:#333333">connector.name=hive-hadoop2
hive.metastore.uri=thrift://node03:9083</span>

6. 分發presto

<span style="color:#333333">cd /kkb/install/
scp -r presto node02:/kkb/install/
scp -r presto node03:/kkb/install/</span>

7. 配置node.properties

  • 進入三臺節點的/kkb/install/presto/etc目錄,修改node.properties檔案

<span style="color:#333333">cd /kkb/install/presto/etc
vim node.properties</span>
  • 三臺節點的內容==分別==如下

<span style="color:#333333"># node01如下內容
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffff1
node.data-dir=/kkb/install/presto/data
​
# node2如下內容
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffff2
node.data-dir=/kkb/install/presto/data
​
# node03如下內容
node.environment=production
node.id=ffffffff-ffff-ffff-ffff-fffffffffff3
node.data-dir=/kkb/install/presto/data</span>

說明:

node.environment 環境的名稱;presto叢集各節點的此名稱必須保持一致

node.id presto每個節點的id,必須唯一

node.data-dir 儲存log及其他資料的目錄

8. 配置config.properties

  • 通過配置config.properties檔案,指明server是coordinator還是worker

  • 雖然presto server可以同時作為coordinator和worker;但是為了更好的效能,一般讓server要麼作為coordinator,要麼作為worker

  • presto是主從架構;主是coordinator,從是worker

  • 現設定node01作為coordinator節點;node02、node03節點作為worker節點

  • node01上配置coordinator

<span style="color:#333333">cd /kkb/install/presto/etc
vim config.properties</span>
  • 新增如下內容

<span style="color:#333333">coordinator=true
node-scheduler.include-coordinator=false
http-server.http.port=8880
query.max-memory=50GB
query.max-memory-per-node=1GB
discovery-server.enabled=true
discovery.uri=http://node01:8880</span>

說明:

coordinator=true 允許此presto例項作為coordinator

node-scheduler.include-coordinator 是否允許在coordinator上執行work

http-server.http.port presto使用http服務進行內部、外部的通訊;指定http server的埠

query.max-memory 一個查詢執行時,使用的所有的分散式記憶體的總量的上限

query.max-memory-per-node query在執行時,使用的任何一個presto伺服器上使用的記憶體上限

discovery-server.enabled presto使用discovery服務,用來發現所有的presto節點

discovery.uri discovery服務的uri

  • node02、node03上配置worker

<span style="color:#333333">cd /kkb/install/presto/etc
vim config.properties</span>
  • 新增如下內容

<span style="color:#333333">coordinator=false
http-server.http.port=8880
query.max-memory=50GB
discovery.uri=http://node01:8880</span>

9. 啟動presto server

  • 若要用presto對接hive資料,需要啟動hive metastore服務

  • 上課環境:hive安裝在node03上,所以在node03啟動metastore服務

<span style="color:#333333">nohup hive --service metastore > /dev/null 2>&1 &</span>
  • 在node01、node02、node03上分別啟動presto server,執行以下命令

<span style="color:#333333">cd /kkb/install/presto
# 前臺啟動,控制檯列印日誌
bin/launcher run
# 或使用後臺啟動presto
bin/launcher start</span>
  • jps檢視,各節點出現名為PrestoServer的程序

  • 日誌所在目錄

<span style="color:#333333">/kkb/install/presto/data/var/log</span>

 

2. 安裝部署Presto命令列介面

1. 下載安裝包

  • 下載地址:

  • 安裝包放到node01的目錄/kkb/soft

2. 重新命名檔案

<span style="color:#333333">cd /kkb/soft
mv presto-cli-0.237-executable.jar prestocli</span>

3. 增加可執行許可權

<span style="color:#333333">chmod u+x prestocli</span>

4. 啟動presto cli

  • 注意:==先啟動HDFS==

  • 檢視presto客戶端jar包的使用方式

<span style="color:#333333">./prestocli --help</span>
  • 兩種方式;方式一

<span style="color:#333333">./prestocli --server node01:8880 --catalog hive --schema default</span>

說明:

--catalog hive 中的hive指的是etc/catalog中的hive.properties的檔名

  • 方式二

<span style="color:#333333">java -jar presto-cli-0.237-executable.jar --server node01:8880 --catalog hive --schema default</span>
  • 退出presto cli

<span style="color:#333333">quit</span>

 

5. 體驗命令操作

Presto的命令列操作,相當於Hive命令列操作。每個表必須要加上schema字首;例如

<span style="color:#333333">select * from schema.table limit 5
​
或者切換到指定的schema,再查詢表資料
use myhive;
select * from score limit 3;</span>

 

3. 安裝部署Presto 視覺化客戶端

1. 下載安裝包

  • presto有個開源的帶視覺化介面的客戶端yanagishima

  • 原始碼下載地址:

  • 將下載的包yanagishima-18.0.zip上傳到node01點/kkb/soft目錄

2. 解壓縮

<span style="color:#333333">cd /kkb/soft
unzip -d /kkb/install yanagishima-18.0.zip
​
# 若出現-bash: unzip: command not found,表示沒有安裝unzip;需要安裝;然後再解壓縮
sudo yum -y install unzip zip
​
cd /kkb/install/yanagishima-18.0</span>

 

3. 修改配置檔案

  • 修改yanagishima.properties檔案

<span style="color:#333333">cd /kkb/install/yanagishima-18.0/conf
vim yanagishima.properties</span>
  • 新增如下內容

<span style="color:#333333">jetty.port=7080
presto.datasources=kkb-presto
presto.coordinator.server.kkb-presto=http://node01:8880
catalog.kkb-presto=hive
schema.kkb-presto=default
sql.query.engines=presto</span>

 

4. 啟動yanagishima

<span style="color:#333333">後臺啟動:nohup bin/yanagishima-start.sh >yanagishima.log 2>&1 &
​
[hadoop@node01 yanagishima-18.0]$ pwd
/kkb/install/yanagishima-18.0
前臺啟動:bin/yanagishima-start.sh
>yanagishima.log </span>
  • node01上多出名為YanagishimaServer的程序

  • 啟動web介面

    在介面中進行查詢了

    若ui介面顯示很慢,或者不顯示,可以嘗試將node01替換成相應的ip地址

  • 查看錶結構;

  • 每個表後面都有個複製鍵,點一下會複製完整的表名,然後再上面框裡面輸入sql語句,ctrl+enter組合鍵或Run按鈕執行顯示結果

  •  

  • 這裡有個Tree View,可以檢視所有表的結構,包括Schema、表、欄位等。

  • 比如執行select * from hive.myhive.score,這個句子裡Hive這個詞可以刪掉,即變成select * from myhive.score;hive是上面配置的Catalog名稱

  • 注意:==sql語句末尾不要加分號;否則報錯==

  •  

5. Presto查詢及優化

 

1. Presto sql語法

  • 以下用hive connector演示

  • 檢視schema有哪些

<span style="color:#333333">SHOW SCHEMAS;</span>
  • 檢視有哪些表

<span style="color:#333333">SHOW TABLES;</span>
  • 建立schema

<span style="color:#333333">語法:CREATE SCHEMA [ IF NOT EXISTS ] schema_name
​
CREATE SCHEMA testschema;</span>
  • 刪除schema

<span style="color:#333333">語法:DROP SCHEMA [ IF EXISTS ] schema_name
drop schema testschema;</span>
  • 建立表

<span style="color:#333333">語法:CREATE TABLE [ IF NOT EXISTS ]
table_name (column_name data_type [ COMMENT comment],... ]
​
create table stu4(id int, name varchar(20));</span>
  • 建立表CTAS

<span style="color:#333333">語法:
CREATE TABLE [ IF NOT EXISTS ] table_name [ ( column_alias, ... ) ]
[ COMMENT table_comment ]
[ WITH ( property_name = expression [, ...] ) ]
AS query
[ WITH [ NO ] DATA ]
​
create table if not exists myhive.stu5 as select id, name from stu1;</span>
  • 刪除表中符合條件的行

<span style="color:#333333">語法:DELETE FROM table_name [ WHERE condition ]
說明:hive connector只支援一次性的刪除一個完整的分割槽;不支援刪除一行資料
​
DELETE FROM order_partition where month='2019-03';</span>
  • 查看錶的描述資訊

<span style="color:#333333">DESCRIBE hive.myhive.stu1;</span>
  • ANALYZE獲得表及列的統計資訊

<span style="color:#333333">語法:ANALYZE table_name
​
ANALYZE hive.myhive.stu1;</span>
  • prepare 給statement起一個名稱,等待將來的執行

  • execute執行一個準備好的statement

<span style="color:#333333">語法:PREPARE statement_name FROM statement
​
prepare my_select1 from select * from score;
execute my_select1;
​
prepare my_select2 from select * from score where s_score < 90 and s_score > 70;
execute my_select2;
​
prepare my_select3 from select * from score where s_score < ? and s_score > ?;
execute my_select3 using 90, 70;</span>
  • EXPLAIN:查詢一個statement的邏輯計劃或分散式執行計劃,或校驗statement

<span style="color:#333333">語法:
EXPLAIN [ ( option [, ...] ) ] statement
​
where option can be one of:
​
    FORMAT { TEXT | GRAPHVIZ | JSON }
    TYPE { LOGICAL | DISTRIBUTED | VALIDATE | IO }
​
查詢邏輯計劃語句:
explain select s_id, avg(s_score) from score group by s_id;
等價於
explain (type logical)select s_id, avg(s_score) from score group by s_id;
​
查詢分散式執行計劃distributed execution plan
explain (type distributed)select s_id, avg(s_score) from score group by s_id;
​
校驗語句的正確性
explain (type validate)select s_id, avg(s_score) from score group by s_id;
​
explain (type io, format json)select s_id, avg(s_score) from score group by s_id;</span>
  • SELECT查詢

<span style="color:#333333">語法:
[ WITH with_query [, ...] ]
SELECT [ ALL | DISTINCT ] select_expr [, ...]
[ FROM from_item [, ...] ]
[ WHERE condition ]
[ GROUP BY [ ALL | DISTINCT ] grouping_element [, ...] ]
[ HAVING condition]
[ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] select ]
[ ORDER BY expression [ ASC | DESC ] [, ...] ]
[ LIMIT [ count | ALL ] ]
​
from_item:
table_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
from_item join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]
​
join_type:
[ INNER ] JOIN
LEFT [ OUTER ] JOIN
RIGHT [ OUTER ] JOIN
FULL [ OUTER ] JOIN
CROSS JOIN
​
grouping_element:
()
expression
GROUPING SETS ( ( column [, ...] ) [, ...] )
CUBE ( column [, ...] )
ROLLUP ( column [, ...] )
​
語句:
with語句:用於簡化內嵌的子查詢
select a, b
from (
select s_id as a, avg(s_score) as b from score group by s_id
) as tbl1;
​
等價於:
with tbl1 as (select s_id as a, avg(s_score) as b from score group by s_id)
select a, b from tbl1;
​
多個子查詢也可以用with
WITH
  t1 AS (SELECT a, MAX(b) AS b FROM x GROUP BY a),
  t2 AS (SELECT a, AVG(d) AS d FROM y GROUP BY a)
SELECT t1.*, t2.*
FROM t1
JOIN t2 ON t1.a = t2.a;
​
with語句中的關係可以串起來(chain)
WITH
  x AS (SELECT a FROM t),
  y AS (SELECT a AS b FROM x),
  z AS (SELECT b AS c FROM y)
SELECT c FROM z;
​
​
group by:
select s_id as a, avg(s_score) as b from score group by s_id;
等價於:
select s_id as a, avg(s_score) as b from score group by 1;
1代表查詢輸出中的第一列s_id
​
select count(*) as b from score group by s_id;</span>

2. 儲存優化

  • 合理設定分割槽

    與Hive類似,Presto會根據元資訊讀取分割槽資料,合理的分割槽能減少Presto資料讀取量,提升查詢效能。

  • 使用列式儲存

    Presto對ORC檔案讀取做了特定優化,因此在Hive中建立Presto使用的表時,建議採用ORC格式儲存。相對於Parquet,Presto對ORC支援更好。

  • 使用壓縮

    資料壓縮可以減少節點間資料傳輸對IO頻寬壓力,對於即席查詢需要快速解壓,建議採用snappy壓縮

  • 預先排序

    對於已經排序的資料,在查詢的資料過濾階段,ORC格式支援跳過讀取不必要的資料。比如對於經常需要過濾的欄位可以預先排序。

 

3. SQL優化

  • 列剪裁

    只選擇使用必要的欄位: 由於採用列式儲存,選擇需要的欄位可加快欄位的讀取、減少資料量。避免採用*讀取所有欄位

<span style="color:#333333">[GOOD]: SELECT s_id, c_id FROM score
​
[BAD]:  SELECT * FROM score</span>
  • 過濾條件必須加上分割槽欄位

    對於分割槽表,where語句中優先使用分割槽欄位進行過濾。day是分割槽欄位,vtime是具體訪問時間

<span style="color:#333333">[GOOD]: SELECT vtime, stu, address FROM tbl where day=20200501
​
[BAD]:  SE LECT * FROM tbl where vtime=20200501</span>
  • Group By語句優化:

    合理安排Group by語句中欄位順序對效能有一定提升。將Group By語句中欄位按照每個欄位distinct資料多少進行降序排列, 減少GROUP BY語句後面的排序一句欄位的數量能減少記憶體的使用.

<span style="color:#333333">uid個數多;gender少
[GOOD]: SELECT GROUP BY uid, gender
​
[BAD]:  SELECT GROUP BY gender, uid</span>
  • Order by時使用Limit, 儘量避免ORDER BY: Order by需要掃描資料到單個worker節點進行排序,導致單個worker需要大量記憶體

<span style="color:#333333">[GOOD]: SELECT * FROM tbl ORDER BY time LIMIT 100
​
[BAD]:  SELECT * FROM tbl ORDER BY time</span>
  • 使用近似聚合函式: 對於允許有少量誤差的查詢場景,使用這些函式對查詢效能有大幅提升。比如使用approx_distinct() 函式比Count(distinct x)有大概2.3%的誤差

<span style="color:#333333">select approx_distinct(s_id) from score;</span>
  • 用regexp_like代替多個like語句: Presto查詢優化器沒有對多個like語句進行優化,使用regexp_like對效能有較大提升

<span style="color:#333333">SELECT
...
FROM
access
WHERE
method LIKE '%GET%' OR
method LIKE '%POST%' OR
method LIKE '%PUT%' OR
method LIKE '%DELETE%'
​
優化:
SELECT
...
FROM
access
WHERE
regexp_like(method, 'GET|POST|PUT|DELETE')</span>
  • 使用Join語句時將大表放在左邊: Presto中join的預設演算法是broadcast join,即將join左邊的表分割到多個worker,然後將join右邊的表資料整個複製一份傳送到每個worker進行計算。如果右邊的表資料量太大,則可能會報記憶體溢位錯誤。

<span style="color:#333333">[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</span>
  • 使用Rank函式代替row_number函式來獲取Top N

  • UNION ALL 代替 UNION :不用去重

  • 使用WITH語句: 查詢語句非常複雜或者有多層巢狀的子 查詢,請試著用WITH語句將子查詢分離出來

6. 其他注意事項

1. 欄位名引用

  • 避免和關鍵字衝突:MySQL對欄位加反引號`;Presto對欄位加雙引號分割

    當然,如果欄位名稱不是關鍵字,可以不加這個雙引號。

2. 函式

  • 對於Timestamp,需要進行比較的時候,需要新增Timestamp關鍵字,而MySQL中對Timestamp可以直接進行比較。

<span style="color:#333333"><span style="color:#aa5500">/*MySQL的寫法*/</span>
<span style="color:#770088">SELECT</span> t <span style="color:#770088">FROM</span> a <span style="color:#770088">WHERE</span> t > <span style="color:#aa1111">'2020-05-01 00:00:00'</span>; 
​
<span style="color:#aa5500">/*Presto的寫法*/</span>
<span style="color:#770088">SELECT</span> t <span style="color:#770088">FROM</span> a <span style="color:#770088">WHERE</span> t > <span style="color:#116644">timestamp '2020-05-01 00:00:00'</span>;</span>

 

3. 不支援INSERT OVERWRITE語法

  • Presto中不支援insert overwrite語法,只能先delete,然後insert into。

4. QUET格式

  • Presto目前支援Parquet格式,支援查詢,但不支援insert

 

五、拓展點、未來計劃、行業趨勢

    • 安裝部署

    • connector

    • function

    • sql statement syntax

 

注:以上來自kkb課堂筆記