文章目錄
- 一、執行計劃
- 1、概念簡介
- 2、使用方式
- ①、EXPLAIN
- ②、EXPLAIN ANALYZE
- 二、算子解讀
- 1、SCAN
- 2、Index Scan和 Index Seek
- 3、Filter
- 4、Decode
- 5、Redistribution
- 6、Join
- 7、Broadcast
- 8、Shard prune和Shards selected
- 9、ExecuteExternalSQL
- 10、Aggregate
- 11、Sort
- 12、Limit
- 13、Append
- 14、Exchange
- 15、Forward
- 16、Project
一、執行計劃
1、概念簡介
EXPLAIN:代表優化器QO根據SQL特征預估的SQL執行計劃,并非實際的執行計劃,對SQL的運行有一定參考意義。
EXPLAIN ANALYZE:代表SQL真實的運行計劃,相比EXPLAIN會包含更多的實際運行信息,能準確的反映出SQL的執行算子和算子耗時,可以根據算子耗時去做針對性的SQL優化。
2、使用方式
①、EXPLAIN
EXPLAIN <sql>;示例:
EXPLAIN SELECTl_returnflag,l_linestatus,sum(l_quantity) AS sum_qty,sum(l_extendedprice) AS sum_base_price,sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,avg(l_quantity) AS avg_qty,avg(l_extendedprice) AS avg_price,avg(l_discount) AS avg_disc,count(*) AS count_order
FROMlineitem
WHEREl_shipdate <= date '1998-12-01' - interval '120' day
GROUP BYl_returnflag,l_linestatus
ORDER BYl_returnflag,l_linestatus;
解釋說明: 執行計劃需要從下往上看,每個箭頭(->)代表一個節點,每個子節點會返回使用的算子,以及預估的行數等。
②、EXPLAIN ANALYZE
EXPLAIN ANALYZE <sql>;示例:
EXPLAIN ANALYZE SELECTl_returnflag,l_linestatus,sum(l_quantity) AS sum_qty,sum(l_extendedprice) AS sum_base_price,sum(l_extendedprice * (1 - l_discount)) AS sum_disc_price,sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,avg(l_quantity) AS avg_qty,avg(l_extendedprice) AS avg_price,avg(l_discount) AS avg_disc,count(*) AS count_order
FROMlineitem
WHEREl_shipdate <= date '1998-12-01' - interval '120' day
GROUP BYl_returnflag,l_linestatus
ORDER BYl_returnflag,l_linestatus;
解釋說明: EXPLAIN ANALYZE的執行結果反映的是真實執行路徑,其結果是一個由多個算子組成的樹狀結構,會反映出每個階段每個算子的詳細執行信息。EXPLAIN ANALYZE的結果主要包括Query Plan、Advice、Cost耗時、Resource資源消耗情況。
二、算子解讀
詳情點擊參考
1、SCAN
Seq Scan表示順序地從表中讀取數據,會進行全表掃描。
2、Index Scan和 Index Seek
如果掃描表有命中索引,根據表的存儲格式(行存或列存) Hologres在底層使用的索引也不同。
1、Clustering_index:表示使用了列存表的索引(例如segment 、clustering等),只要查詢命中索引就會使用Clustering_index。
2、Index Seek(又名pk_index):表示使用了行存表的索引,主要是主鍵索引。
3、Filter
Filter代表將數據根據SQL條件進行過濾,一般會跟隨seq scan on table一起,是seq scan的子節點,表示掃描表時是否有過濾,以及過濾條件是否命中索引。
主要包括: Filter、Segment Filter、Cluster Filter、Bitmap Filter、Join Filter
4、Decode
Decode表示對數據進行解碼或者編碼,以加速text等文本類數據的計算。
5、Redistribution
Redistribution表示數據通過哈希分布或者隨機分布,查詢時shuffle到一個或者多個shard。
如果出現redistribution,則說明沒有利用local join的能力,導致查詢性能不佳。沒有利用有兩種情況
1.distribution key設置不合理
2.對應的key(如join key、group by key)涉及到表達式時
6、Join
多表關聯(Join)根據SQL的書寫方式又分為hash join、nested loop和merge join。
Hash Join: hash join是指兩個表或者多表join時,基于其中一個表(一般為小表)在內存中構建一個hash表,并把join的列值進行hash計算后放進hash表中,之后逐行的讀取另外的表,計算出其hash值并在hash表中查找,最終返回匹配的數據。當出現hash join時,我們需要額外關注join表中的小表(數據量較小的表)是否是做了hash表,可以通過如下幾種方式查看:
1、執行計劃中,有hash字樣的表是hash表。
2、執行計劃中,從下往上看,最下面的表則是hash表。
Nested Loop Join和Materialize:
Nested Loop代表嵌套循環連接,多表關聯時,先從一張表中讀取數據,成為外層表,再將外層驅動表的每條數據遍歷另外的表(即內層表),然后內外層表嵌套循環進行Join,相當于計算笛卡爾積。在執行計劃中第一內層表通常有Materialize算子。
7、Broadcast
Broadcast指通過廣播的方式將數據分發到各個shard,通常用在Broadcast Join的場景中,一般是小表join大表。
8、Shard prune和Shards selected
Shard prune: 表示獲取Shard的方式,包括:
lazaily:根據節點中的Shard ID先標記對應的Shard,在后續計算時選擇對應的Shard。
eagerly:根據命中的Shard選擇對應的Shard,不需要的Shard則不需要選擇。
優化器會根據執行計劃來自動匹配Shard prume的方式,無需手動調節。
Shards selected: Shards selected表示選中了多少個Shard,例如1 out of 20表示在20個Shard中選中了一個Shard。
9、ExecuteExternalSQL
Hologres的計算引擎會分為HQE、PQE、SQE等,其中PQE是原生Postgres引擎,部分Hologres自研引擎HQE還沒有支持的算子和函數,會通過PQE執行,相比于HQE,PQE的執行效率會更低。當我們在執行計劃中看到有ExecuteExternalSQL算子,說明有函數或者算子走了PQE。
10、Aggregate
Aggregate代表將數據聚合,可以是一個聚合函數或者多個聚合函數的組合。
- GroupAggregate:表示數據已經按照group by進行了預排序。
- HashAggregate(最常見):表示數據先進行hash計算,然后通過hash值分發至不同的shard進行聚合,最終通過Gather算子聚合。
- 多階段HashAggregate:數據是在shard中按照文件存儲的,文件有不同的層級,當數據量多時,聚合的階段也會分為多個階段。主要的子算子包括:
Partial HashAggregate:文件和shard內的聚合。
Final HashAggregate:多個shard上的數據聚合在一起。
11、Sort
sort表示將數據按順序排序(升序ASC或者降序DESC),通常是order by子句的結果。
調優建議:如果order by的數據量較大,將會消耗較多的資源,需要盡量避免大數據量的排序查詢。
12、Limit
limit表示SQL最終允許返回的數據行數。并不代表實際計算中掃描的行數
13、Append
子查詢的結果合并,通常為Union All操作。
14、Exchange
Shard內的數據交換。無需過多關注。
15、Forward
Forward代表將算子的數據在HQE與PQE或者SQE之間傳輸,一般是HQE+PQE或者HQE+SQE的組合會出現。
16、Project
Project一般表示子查詢與外層查詢的映射關系,無需過多關注。