1.為數據存儲選擇合適的文件格式(如:Parquet)
通常對於大數據量來說,Parquet文件格式是最佳的
2. 防止入庫時產生大量的小文件(insert ... values會產生大量小文件,應該避免使用)
在impala外生成數據時,最好是text格式或者Avro,這樣你就可以逐行的構建文件,到了impala之后,再通過簡單的insert ... select語句將其轉換為Parquet格式
3. 根據實際的數據量大小選擇合適的分區粒度
合適的分區策略可以對數據進行物理拆分,在查詢的時候就可以忽略掉無用數據,提高查詢效率,通常建議分區數量在3萬以下(太多的分區也會造成元數據管理的性能下降)
4. 為分區key選擇最小的整數類型
雖然使用string類型也可以作為分區key,因為分區key最后都是作為HDFS目錄使用,但是使用最小的整數類型作為分區key可以降低內存消耗
5. 選擇合適的Parquet塊大小
默認情況下,Impala的insert ... select語句創建的Parquet文件都是每個分區256M(在2.0之后改為1G了),通過Impala寫入的Parquet文件只有一個塊,因而只能被一個機器當作一個單元進行處理。如果在你的Parquet表中只有一個或者幾個分區,或者一個查詢只能訪問一個分區,那么你的性能會非常慢,因為沒有足夠的數據來利用Impala並發分布式查詢的優勢。
6. 在追求性能或者大數據量查詢的時候,要先獲取所需要的表的統計指標(如:執行compute stats)
7. 減少傳輸到client端的數據量
聚合(如 count、sum、max等)
過濾(如WHERE)
LIMIT
結果集禁止使用美化格式進行展示(在通過impala-shell展示結果時,添加這些可選參數:-B、 --output_delimiter)
8.通過EXPLAIN Plans和Query Profiles來了解Impala查詢性能
想要了解Impala查詢的高性能注意事項,可以閱讀查詢的EXPLAIN輸出,你可以獲取EXPLAIN的執行計划,而無須真正的執行query。
想要查看一個查詢的物理性能特性的概覽,可以在執行查詢之后立馬在impala-shell中執行SUMMARY命令,輸出的信息中將展示哪個階段耗時最多,以及每一階段估算的內存消耗、行數與實際的差異。
想要了解查詢的詳細性能特征,可以在執行查詢之后立馬在impala-shell中執行PROFILE命令,這些底層的信息包括內存、CPU、I/O以及網絡消耗的詳細信息,因此只能在一個真實的查詢之后才可用。
EXPLAIN --你可以獲取EXPLAIN的執行計划,而無須真正的執行query
PROFILE --PROFILE語句將產生一個關於最近一次查詢的底層報告的詳細信息展示。與EXPLAIN不同,這些信息只在查詢完成之后才會生成,它顯示了每個節點上的物理詳細信息如:讀取的字節數,最大內存消耗等
SUMMAY --命令可以輸出每一階段的耗時,可以快速地了解查詢的性能瓶頸,SUMMARY輸出也會在PROFILE的頭部輸出的顯示。
explain
sql sql profile/summay
需要根據具體的計划來調節SQL內容
9.join 的算法
1. hash join: 對於等值join, impala將采用hash的方式處理, 具體又分兩種策略, broadcast 和 Shuffle.
broadcast join 非常適合右表是小表的情形, impala 先將右表復制到各個節點, 再和左表做join.
shuffle join, 也叫做partitioned join, 適合大表和大表關聯. 注意 partitioned join 和右表的 partition 沒有直接關系, impala 會將右表打散成N份, 發送到左表所在的節點, 然后作join.
2. nested loop join: 針對非等值join, impala將使用 nested loop join, 這時我們不能設置 SHUFFLE/BROADCAST hint, 也不能使用 spill disk 功能. impala的非等值join的效率較低, Vertica的效率非常高, Hive直接不支持.
SELECT STRAIGHT_JOIN select_list FROM
join_left_hand_table
JOIN [{ /* +BROADCAST */ | /* +SHUFFLE */ }]
join_right_hand_table
remainder_of_query;
/* +SHUFFLE */ 即 partitioned join, 是將要關聯的兩個表按照
/* +BROADCAST */ 因為當表和索引統計信息不可用時,默認方式
最佳實踐
Impala執行引擎還不是那么智能, 多表join 的SQL最好還是按照下面的推薦的寫法:
1. 最大的表應該放在表清單的最左邊.
2. 多個join的查詢語句, 應該將選擇性最強的join放在最前面.
3. 定期對表收集統計信息, 或者在大量DML操作后主動收集統計信息.
4. 在一個單一的查詢里面, 參加join的表個數盡量不要超過4個, 不然效率比較低下.