概述
基于Hive的大資料實時分析查詢引擎,
Hive適合于長時間的批處理查詢分析,而Impala適合于實時互動式SQL查詢,
建表陳述句
建表陳述句中的location指向實際資料的路徑;
了解一個表的基本類別可以通過show create table命令;
洗掉impala的一行資料:不是delete
基本概念
元資料與資料
元資料是記錄資料的資料,Impala的資料就是檔案,而元資料是記錄檔案存在什么位置,多少個,大小,時間等,
重繪
invalidate metadata和refresh
refresh輕量級,適用于資料更新(不是Impala途徑增加或者洗掉資料)的場景;
invalidate metadata,適用于表結構發生改變(非Impala途徑創建或者修改表結構);
統計資訊
收集統計資訊:compute stats db.table
查看表統計資訊:show table stats db.table
查看欄位統計資訊:show column stats db.table
用途:
join query缺少統計資訊時,可能會生成錯誤的執行計劃,查詢緩慢;
join
join演算法有兩類:
- hash join:對于等值join,Impala將采用hash的方式處理,具體又分兩種策略:broadcast 和 Shuffle,
- broadcast join 非常適合右表是小表的情形,Impala先將右表復制到各個節點,再和左表做join
- shuffle join:亦partitioned join,適合大表和大表關聯,partitioned join 和右表的 partition 沒有直接關系,Impala會將右表打散成N份,發送到左表所在的節點,然后join;有點類似于mapreduce中的shuffle
- nested loop join:針對非等值join,Impala將使用 nested loop join,這時不能設定 SHUFFLE/BROADCAST hint,也不能使用 spill disk 功能,Impala的非等值join的效率較低,Vertica的效率非常高,Hive直接不支持
broadcast vs shuffle
broadcast,廣播連接,Impala默認方式,大表一定要放在左邊,因為impala在廣播右側表,所有右側表會復制到需要右側表進行聯接的所有節點,右側的表被認為比左側的表小,并且它的內容被發送到查詢涉及到的其他節點上,
在join后面加[shuffle],將broadcast join轉換為shuffle join,
替代的技術稱作分割連接(partitioned join,與磁區表無關),更適用于近乎相同大小的大型表的連接,每一個表的部分內容被發送到對應的其他節點,然后這些行的子集可以并行處理,廣播和磁區連接的選擇仍然依賴于連接中所有表的可用的、使用 COMPUTE STATS 陳述句的統計資訊,
Impala join查詢最簡單的優化手段就是通過使用compute stats來收集join中每張表的統計資訊,然后由Impala根據表的大小、列的唯一值數目等來自動優化查詢,為了更加精確地獲取每張表的統計資訊,每次表的資料變更時(如執行insert、load data、add partition、或drop partition等)都要重新執行一遍compute stats,
如果join查詢中表的統計資訊不全或者Impala選擇的join順序不是最優時,你可以在select [distinct 、all]之后指定straight_join來覆寫掉impala的join順序如:
select straight_join x
from medium join small join (select * from big where c1 < 10) as big
where medium.id = small.id
and small.id = big.id;
select distinct straight_join x
from medium join small join (select * from big where c1 < 10) as big
where medium.id = small.id
and small.id = big.id;
這樣Impala就會使用查詢陳述句中表的順序來指導join的處理,
當使用STRAIGHT_JOIn技術時,你必須手動指定join查詢中表的順序而不是依賴于Impala優化器,Impala優化器使用特殊的手段來估算join中每個階段的結果集大小,而對于手動指定順序來說,可以根據如下方式開始,然后再手動調節來達到最優:
首先指定最大的表,此表一般保存于磁盤中
指定最小的表,第二張表、第三張表等等之后的表都是通過網路傳輸的,你需要對這些結果集進行裁剪處理以降低傳輸資料量
指定次小表,再到次次小表等
例如:如果你的表的大小如下:BIG、MEDIUM、SMALL和TINY,那么你的順序應該如此:BIG join TINY join SMALL join MEDIUM,
Impala查詢優化器根據表的絕對或者相對大小來選擇不同技術來執行join查詢,默認情況下是 broadcast join,右邊的表都是小于左邊的表,右邊的表的內容會被分發到其他的查詢節點中,
另一種技術就是partitioned join,這種技術更加適用于大小差不多大的大表join,使用這種方式的話,每張表中的磁區都會把資料分發到其他節點中,這樣就可以這些資料子集就可以并發處理了, broadcast或者partition join的選擇是根據compute stats采集到的可用統計指標來衡量的,對于指定查詢陳述句,可以通過執行EXPLAIN就可以查看選用的是哪個join策略,
統計指標不可用時join如何查詢
?? 當join中表或者列的統計指標不可用時,Impala將無統計指標的表認為統計指標都為0,這些表都將作為右表處理,
外部表
創建表的時候可以通過指定location來指定表檔案的存放路徑,如果不指定的話,默認是將資料存放在/user/hive/warehouse/庫名下,
未被external修飾的表是內部表(managed table),被external修飾的是外部表(external table)
區別:
- 內部表的資料是由Hive自身管理的,外部表的資料是由HDFS管理的;
- 洗掉內部表會洗掉存盤在hive元資料庫的元資料和存盤在HDFS的檔案資料;洗掉外部表只洗掉元資料不洗掉存盤的資料;
- 兩者都可以在建表的時候指定location,指定資料檔案的存放位置;如果不指定的話,默認都是在
/user/hive/warehouse/目錄下(這個目錄是可以在組態檔中修改的), - 兩者的load 操作都會移動資料
磁區表
存盤格式
通常對于大資料量來說,Parquet檔案格式是最佳的
運算子
Impala特有運算子
ILIKE:忽略大小寫的 like 運算子
REGEXP:正則匹配運算子
RLIKE:同 REGEXP 運算子
IREGEXP:忽略大小寫的正則匹配符
IS DISTINCT FROM:判斷前后兩個運算式是否不相等,和<>運算子類似,但 null IS DISTINCT FROM null 回傳 false
IS not DISTINCT FROM:判斷前后兩個運算式是否相等,和=運算子類似,唯一不同的是,處理 null 時候,null IS not DISTINCT FROM null 結果為 ture
例外
set DISABLE_UNSAFE_SPILLS=0/FALSE; #0(FALSE)記憶體運算瀕臨溢位時轉為磁盤運算,1(TRUE)時,當記憶體溢位時直接報記憶體溢位“Memory limit exceeded”錯誤
set mem_limit=-1 #取消記憶體限制;
java.sql.SQLException:memory limit exceeded常見原因:
優化技巧
在優化之前,可先拿到查詢計劃,類似mysql explain查詢計劃,在執行后也可以查看詳細的執行資訊,
查詢計劃
Impala提供三種方式得知查詢計劃
- EXPLAIN:獲取執行計劃,而無須真正的執行query
- PROFILE:產生一個關于最近一次查詢的底層報告的詳細資訊展示,與EXPLAIN不同,這些資訊只在查詢完成之后才會生成,它顯示每個節點上的物理詳細資訊如:讀取的位元組數,最大記憶體消耗等,
想要查看一個查詢的物理性能特性的概覽,可以在執行查詢之后立馬在impala-shell中執行PROFILE命令,輸出的資訊中將展示哪個階段耗時最多,以及每一階段估算的記憶體消耗、行數與實際的差異,進行性能分析,可根據這些資訊來確定查詢時I/O密集型,還是CPU密集型,網路是否導致瓶頸,是否某些節點性能差但是其它節點性能好等資訊, - SUMMAY:輸出每一階段的耗時,可以快速地了解查詢的性能瓶頸,SUMMARY輸出也會在PROFILE的頭部輸出的顯示,
想要了解查詢的詳細性能特征,可以在執行查詢之后立馬在impala-shell中執行PROFILE命令,這些底層的資訊包括記憶體、CPU、I/O以及網路消耗的詳細資訊,只能在一個真實的查詢之后才可用,
EXPLAIN陳述句概述了查詢將執行的邏輯步驟,例如如何在節點間分配作業以及中間結果如何合并為最終結果, 這些你都可以在查詢真正執行之前獲得,你可以使用這些資訊來檢查查詢是否會以某種非高效的方式執行,
explain select ds,count(*) from t_ed_xxxx_newuser_read_feature_n group by ds order by ds;
+----------------------------------------------------------------------------------------------+
| Explain String |
+----------------------------------------------------------------------------------------------+
| Max Per-Host Resource Reservation: Memory=9.94MB |
| Per-Host Resource Estimates: Memory=27.00MB |
| |
| PLAN-ROOT SINK |
| | |
| 05:MERGING-EXCHANGE [UNPARTITIONED] |
| | order by: ds ASC |
| | |
| 02:SORT |
| | order by: ds ASC |
| | |
| 04:AGGREGATE [FINALIZE] |
| | output: count:merge(*) |
| | group by: ds |
| | |
| 03:EXCHANGE [HASH(ds)] |
| | |
| 01:AGGREGATE [STREAMING] |
| | output: sum_init_zero(default.t_ed_xxxx_newuser_read_feature_n.parquet-stats: num_rows) |
| | group by: ds |
| | |
| 00:SCAN HDFS [default.t_ed_xxxx_newuser_read_feature_n] |
| partitions=372/372 files=2562 size=15.15GB
自底向上讀取EXPLAIN的輸出:
00階段: 顯示了底層的詳細資訊,如:掃描的表,表的磁區數,檔案數以及檔案大小等資訊,根據這些資訊,你可以估算大概的耗時
01階段: 聚合操作SUM并行地在不同的節點上執行
03階段: 將01階段的結果進行傳輸
04階段: 將SUM結果進行合并
02階段: 排序操作并行地在不同的節點中進行
05階段: 排序結果合并,并且輸出
EXPLAIN也會在PROFILE結果的頭部輸出,
SUMMARY命令可以輸出每一階段的耗時,可以快速地了解查詢的性能瓶頸,與PROFILE輸出一樣,它只能在查詢之后才可用,并且顯示實際的時間消耗,SUMMARY輸出也會在PROFILE的頭部輸出的顯示,
select ds,count(*) from t_ed_xxxx_newuser_read_feature_n group by ds order by ds;
summary;
+---------------------+--------+----------+----------+-------+------------+----------+---------------+--------------------------------------------+
| Operator | #Hosts | Avg Time | Max Time | #Rows | Est. #Rows | Peak Mem | Est. Peak Mem | Detail |
+---------------------+--------+----------+----------+-------+------------+----------+---------------+--------------------------------------------+
| 05:MERGING-EXCHANGE | 1 | 3.20s | 3.20s | 372 | 372 | 0 B | 0 B | UNPARTITIONED |
| 02:SORT | 51 | 517.22us | 2.54ms | 372 | 372 | 6.02 MB | 6.00 MB | |
| 04:AGGREGATE | 51 | 1.75ms | 7.85ms | 372 | 372 | 2.12 MB | 10.00 MB | FINALIZE |
| 03:EXCHANGE | 51 | 2.91s | 3.10s | 2.44K | 372 | 0 B | 0 B | HASH(ds) |
| 01:AGGREGATE | 51 | 135.29ms | 474.62ms | 2.44K | 372 | 2.03 MB | 10.00 MB | STREAMING |
| 00:SCAN HDFS | 51 | 1.08s | 2.58s | 2.56K | 96.53M | 1.05 MB | 1.00 MB | default.t_ed_xxxx_newuser_read_feature_n |
PROFILE和SUMMAY區別
profile:輸出底層資訊計劃
summary:查看查詢時間及占用記憶體
區別不重要,都可用,
除了查詢計劃,可以
- 為資料存盤選擇合適的檔案格式(如Parquet),通常對于大資料量來說,Parquet檔案格式是最佳
- 防止入庫時產生大量的小檔案(
insert ... values會產生大量小檔案,應該避免使用)
在impala外生成資料時,最好是text格式或Avro,可逐行的構建檔案,到impala后再通過簡單的insert ... select陳述句將其轉換為Parquet格式. - 根據實際的資料量大小選擇合適的磁區粒度
合適的磁區策略可以對資料進行物理拆分,查詢時可以忽略掉無用資料,提高查詢效率,通常建議磁區數量在3萬以下(太多的磁區也會造成元資料管理的性能下降) - 為磁區key選擇最小的整數型別
雖然使用string型別也可以作為磁區key,因為磁區key最后都是作為HDFS目錄使用,但是使用最小的整數型別作為磁區key可以降低記憶體消耗 - 選擇合適的Parquet塊大小
默認情況下,Impala的insert ... select陳述句創建的Parquet檔案都是每個磁區256M(在2.0之后改為1G),通過Impala寫入的Parquet檔案只有一個塊,因而只能被一個機器當作一個單元進行處理,如果在你的Parquet表中只有一個或者幾個磁區,或者一個查詢只能訪問一個磁區,那么你的性能會非常慢,因為沒有足夠的資料來利用Impala并發分布式查詢的優勢, - 在追求性能或者大資料量查詢時,要先獲取所需要的表的統計指標(如執行
compute stats) - 減少傳輸到client端的資料量,如:使用聚合(如 count、sum、max等)、過濾(如WHERE)、LIMIT
結果集禁止使用美化格式進行展示(在通過impala-shell展示結果時,添加這些可選引數:-B, --output_delimiter) - 選擇合適的join演算法
具體地:
- 最大的表應該放在表清單的最左邊
- 多個join的查詢陳述句,應該將選擇性最強的join放在最前面
- 定期對表收集統計資訊或在大量DML操作后主動收集統計資訊
- 在單一join查詢中,涉及到的資料表個數盡量不要超過4個,不然效率比較低下
COMPUTE STATS
和HIVE的ANALYZE TABLE類似,這個命令主要也是為了優化查詢,加快查詢的速度,本來IMPALA是依靠HIVE的ANALYZE TABLE的,但是這個命令不是很好用同時不穩定,所以IMPALA自己實作了個命令完成相同功能,
有兩類,語法:
# 全量
COMPUTE STATS [db_name.]table_name
# 增量
COMPUTE INCREMENTAL STATS [db_name.]table_name [PARTITION (partition_spec)]
作用:
收集有關表中資料的容量和分布以及所有相關列和磁區的資訊,這些資訊存盤在metastore資料庫中,Impala使用這些資訊來幫助優化查詢,
區別:
參考
Impala性能優化總結
Apache Impala 性能優化
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/240875.html
標籤:其他
上一篇:事務的特征與隔離級別
