Impala 性能調整
下面的章節介紹影響 Impala 功能性能的各種因素,并對 Impala 查詢和其他 SQL 操作進行性能調整、監控和基準測試。
這一章節同樣描述了最大化 Impala 可擴充性的技術。可擴充性與性能相關:它意味着當系統負載增加時仍保持高性能(Scalability is tied to performance: it means that performance remains high as the system workload increases)。例如,減少查詢的硬碟 I/O 可以加快單個的查詢,與此同時,導緻可以同時運作更多查詢,進而提升了可擴充性。有時候,一種優化技術提升了性能的同時更增加了可擴充性。例如,減少查詢的記憶體使用可能不會很大的提高查詢性能,但是通過允許同時運作更多的 Impala 查詢或其他類型的作業而不會耗盡記憶體,進而提升了可擴充性。

:
在開始任何性能調整和基準測試之前,請確定你的系統已經按照 Post-Installation Configuration for Impala 中的設定進行配置。
- Partitioning. 這一技術基于頻繁查詢的列上的不同的值,把資料實體拆分開來,允許查詢跳過讀取表中很大部分的資料
- Performance Considerations for Join Queries. 相對于修改實體因素,如檔案格式或硬體配置,連接配接是你可以在 SQL 層級進行調整的主要方面(Joins are the main class of queries that you can tune at the SQL level, as opposed to changing physical factors such as the file format or the hardware configuration)。對于連接配接的性能,相關的主題 Column Statistics 和 Table Statistics 同樣重要
- Table Statistics and Column Statistics. 使用 COMPUTE STATS 語句,采集表和列的統計資訊,幫助 Impala 自動優化連接配接查詢的性能,而不需要修改 SQL 查詢語句(在 Impala 1.2.2 及以上版本,這一過程特别簡單,因為 COMPUTE STATS 語句在同一個語句中同時采集兩種資訊,而且不需要像之前在 Hive 中運作 ANALYZE TABLE 語句那樣,不再需要執行任何設定和配置)
- Testing Impala Performance. 在進行任何基準測試之前,執行一些安裝後測試(post-setup testing),以確定 Impala 使用了性能最優的設定
- Benchmarking Impala Queries. 用于 Impala 初始實驗的配置和樣本資料通常不适合進行性能測試(The configuration and sample data that you use for initial experiments with Impala is often not appropriate for doing performance tests)
- Controlling Resource Usage. 更多記憶體,更加性能(The more memory Impala can utilize, the better query performance you can expect)。在一個同樣運作其他負載的叢集中,你必須權衡考慮,保證所有 Hadoop 元件具有能良好運作的足夠記憶體,是以你可能限制 Impala 可使用的記憶體
分區
表的所有資料檔案預設放在一個目錄下。分區是一項基于一個或多個上的值,在載入時實體拆分資料的技術。例如,對于根據 year 列分區的 school_records 表來說,對于每一個不同的年份都有一個單獨的資料目錄,并且這一年的所有資料都存放在這個目錄下的資料檔案中。一個包含 WHERE 條件如 YEAR=1966, YEAR IN (1989,1999), YEAR BETWEEN 1984 AND 1989 的查詢,可以隻從對應的一個或多個目錄下檢索資料檔案,極大的減少了讀取和測試的資料的數量。
分區通常對應:
- 非常大的表,完整讀取整個資料集花費的時間不可想象(where reading the entire data set takes an impractical amount of time)
- 全部或幾乎所有的查詢都包含分區列查詢條件的表。我們上面的例子中那個根據 year 分區的表, SELECT COUNT(*) FROM school_records WHERE year = 1985 是高效的,隻檢索資料的一小部分;但是 SELECT COUNT(*) FROM school_records 則必須處理每一年的單獨的資料檔案,導緻必未分區表更多的工作。假如你頻繁基于 last name, student ID, 等等不檢測年份的對表進行查詢,考慮不分區表
- 列包含合理的基數(cardinality--不同值的個數)。假如列隻包括少量的值,如 Male 或 Female,你無法通過對每一個查詢消除大約 50% 資料的讀取來獲得更高的效率。假如列的每一個值隻對應很少的行,要處理的目錄的數量會變成一個限制因素,并且每一個目錄中的資料檔案可能太小了,無法從 Hadoop 以 multi-megabyte 塊傳輸資料的機制受益。例如,你可能用年來分區人口資料,用年和月來存放銷售資料,用年月日來分區網絡流量資料(一些更高流量的使用者甚至用小時和分鐘來分區資料)
- 總是使用抽取、轉換、加載(ETL)管道加載的資料。分區列的值從原始的資料檔案剝離,并對應到目錄名中,是以加載資料到分區表涉及了某種轉換或預處理(The values of the partitioning columns are stripped from the original data files and represented by directory names, so loading data into a partitioned table involves some sort of transformation or preprocessing)
在 Impala SQL 文法中,分區會影響到這些語句:
- CREATE TABLE: 在建立表時,使用 PARTITIONED BY 子句來辨別分區列的名稱和資料類型。表中的列不包括這些分區列
- ALTER TABLE: 可以添加或删除分區,用于處理海量資料集的不同部分。對于根據日期值分區的資料,你可以不再保留"過期(age out)"的資料
- INSERT: 當向分區表插入資料時,需要辨別分區列。對于插入的每一行,分區列的值沒有儲存在資料檔案裡,而是根據行存儲的目錄名稱确定。也可以使用 INSERT OVERWRITE 語句來加載一組資料到指定的分區;你可以替換指定分區的内容但是不能向指定分區追加資料
- 盡管表分區與否的 SELECT 語句的文法相同,對分區表的查詢方式可能對性能和可擴充性産生戲劇性的影響。在查詢過程中,讓查詢跳過某些分區的機制稱作分區修剪(partition pruning);參見 Partition Pruning for Queries 了解詳細資訊
參見 Attaching an External Partitioned Table to an HDFS Directory Structure 中的例子,示範了建立分區表的文法,HDFS 中底層的目錄結構,以及如何連接配接到 Impala 外部分區表中存出來 HDFS 其他位置的資料檔案(how to attach a partitioned Impala external table to data files stored elsewhere in HDFS)
參見 Partitioning for Parquet Tables 了解 Parquet 分區表的性能注意事項。
參見 NULL 了解分區表中 NULL 值如何對應。
針對查詢進行分區修剪(Partition Pruning)
分區修剪(Partition pruning)指的是一種查詢可以跳過一個或多個分區對應的資料檔案不進行讀取的技術。假如你能安排你的查詢從查詢計劃中剪除大量的不必要的分區,查詢使用更少的資源,是以與剪除的不必要的分區成比例的變快,并且更可擴充(If you can arrange for queries to prune large numbers of unnecessary partitions from the query execution plan, the queries use fewer resources and are thus proportionally faster and more scalable)。
例如,如果一個表使用 YEAR, MONTH, DAY 分區,這樣如 WHERE year = 2013, WHERE year < 2010, WHERE year BETWEEN 1995 AND 1998 等 WHERE 子句允許 Impala 除了指定範圍的分區外,跳過所有其他分區的資料檔案。同樣的,WHERE year = 2013 AND month BETWEEN 1 AND 3 甚至可以剪除更多的分區,隻讀取一年中的一部分資料檔案。
在執行查詢之前,通過檢查 EXPLAIN 查詢的輸出來檢查查詢分區修剪的效果。例如,下面例子中的表有 3 個分區,而查詢隻讀取其中 1 個。EXOLAIN 計劃中的辨別符 #partitions=1/3 證明 Impala 可以進行對應的分區修剪。
[localhost:21000] > insert into census partition (year=2010) values ('Smith'),('Jones');
[localhost:21000] > insert into census partition (year=2011) values ('Smith'),('Jones'),('Doe');
[localhost:21000] > insert into census partition (year=2012) values ('Smith'),('Doe');
[localhost:21000] > select name from census where year=2010;
+-------+
| name |
+-------+
| Smith |
| Jones |
+-------+
[localhost:21000] > explain select name from census where year=2010;
+------------------------------------------------------------------+
| Explain String |
+------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| PARTITION: UNPARTITIONED |
| |
| 1:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 1 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=predicate_propagation.census #partitions=1/3 size=12B |
+------------------------------------------------------------------+
通過WHERE 子句中其他部分的中間屬性,甚至在分區鍵列沒有明确指定常量值的時候,Impala 都可以進行分區修剪(Impala can even do partition pruning in cases where the partition key column is not directly compared to a constant, by applying the transitive property to other parts of the WHERE clause)。這一技術稱為謂詞傳播(predicate propagation),自 Impala 1.2.2 開始可用。在下面例子裡,表 census 中包含另一個列存放資料收集的時間(是 10 年采集的)。即使分區鍵列 (YEAR) 沒有對應一個常量, Impala 也可以推斷隻有 YEAR=2010 分區是必需的,并再次隻讀取了總分區中 1/3 個分區。
[localhost:21000] > drop table census;
[localhost:21000] > create table census (name string, census_year int) partitioned by (year int);
[localhost:21000] > insert into census partition (year=2010) values ('Smith',2010),('Jones',2010);
[localhost:21000] > insert into census partition (year=2011) values ('Smith',2020),('Jones',2020),('Doe',2020);
[localhost:21000] > insert into census partition (year=2012) values ('Smith',2020),('Doe',2020);
[localhost:21000] > select name from census where year = census_year and census_year=2010;
+-------+
| name |
+-------+
| Smith |
| Jones |
+-------+
[localhost:21000] > explain select name from census where year = census_year and census_year=2010;
+------------------------------------------------------------------+
| Explain String |
+------------------------------------------------------------------+
| PLAN FRAGMENT 0 |
| PARTITION: UNPARTITIONED |
| |
| 1:EXCHANGE |
| |
| PLAN FRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 1 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=predicate_propagation.census #partitions=1/3 size=22B |
| predicates: census_year = 2010, year = census_year |
+------------------------------------------------------------------+
在執行查詢之後,立刻檢查 PROFILE 語句的輸出,了解實際讀取和處理的資料量更詳細的分析。
假如是在分區表上建立的視圖,所有的分區修剪都是由原使得查詢子句确定。即使在試圖上的查詢包含了引用分區鍵列的 WHERE 子句,Impala 不會修剪添加的列(If a view applies to a partitioned table, any partition pruning is determined by the clauses in the original query. Impala does not prune additional columns if the query on the view includes extra WHEREclauses referencing the partition key columns)。
分區鍵列
你選擇的分區列應當是那種經常在重要的、大型的查詢中過濾查詢結果的列。通常來說,資料與時間值有關時,使用年、月、日的組合作為分區列,資料與一些位置有關時使用地理區域作為分區列。
- 對于基于時間的資料,拆分出其中的各個部分到單獨的列,因為 Impala 不能基于 TIMESTAMP 列進行分區
- 分區列的資料類型對存儲需求方面沒有明顯的影響,因為分區列的值不是存放在資料檔案裡,而是在 HDFS 目錄名對應的字元串裡
- Remember that when Impala queries data stored in HDFS, it is most efficient to use multi-megabyte files to take advantage of the HDFS block size. 對于 Parquet 表,塊大小 (資料檔案理想大小) 是 1GB。是以,應避免指定太多分區鍵列,這樣會導緻個别分區隻包含少量資料。例如,假如你每天擷取 1GB 資料,你可能使用年、月、日進行分區;當你每分鐘擷取 5GB 資料時,你可能使用年、月、日、時、分來分區。假如你的資料保護地理元件,假如你每個郵編都有很多M的資料時,你可以基于郵編分區;假如不是,那麼你可能需要使用更大的區域,如 city, state, 或 country. state 分區。
為分區設定不同的檔案格式
分區表具有為不同的分區設定不同的檔案格式的靈活性。例如,你原來是接收文本格式資料,然後是 RCFile 格式,最終會接收 Parquet 格式,所有這些資料可以存放在同一個表裡進行查詢。你隻需要確定該表的結構是使用不同檔案格式的的資料檔案分别在單獨的分區。
例如,下面是當你收到不同年份的資料時,你可能從文本切換到 Parquet:
[localhost:21000] > create table census (name string) partitioned by (year smallint);
[localhost:21000] > alter table census add partition (year=2012); -- Text format;
[localhost:21000] > alter table census add partition (year=2013); -- Text format switches to Parquet before data loaded;
[localhost:21000] > alter table census partition (year=2013) set fileformat parquet;
[localhost:21000] > insert into census partition (year=2012) values ('Smith'),('Jones'),('Lee'),('Singh');
[localhost:21000] > insert into census partition (year=2013) values ('Flores'),('Bogomolov'),('Cooper'),('Appiah');
如上所述,HDFS 目錄 year=2012 包含文本格式資料檔案,而 HDFS 目錄 year=2013 包含 Parquet 資料檔案。一如既往,當加載實際資料時,你應當使用 INSERT ... SELECT 或 LOAD DATA 來導入大批量的資料,而不是使用産生少量的對實際查詢低效的檔案的 INSERT ... VALUES 語句。
對于其他的 Impala 無法本地建立的檔案類型,你可以切換到 Hive 并執行 ALTER TABLE ... SET FILEFORMAT 語句,并在這裡執行 INSERT 或 LOAD DATA 語句。當切換回 Impala 後,執行 REFRESH table_name 語句以便 Impala 感覺到通過 Hive 添加的任意分區或新資料。
連接配接查詢性能注意事項
涉及連接配接操作的查詢通常比隻引用單個表的查詢更需要調整。連接配接查詢結果集的最大大小是所有連接配接的表中行數的乘積。當連接配接幾個百萬或十億記錄的表時,任何過濾結果集的失誤,或查詢中其他的低效操作,都将會導緻操作無法完成不得不取消 。
調整 Impala 連接配接查詢的最簡單的技術就是在參與連接配接的每個表上使用 COMPUTE STATS 語句采集統計資訊,然後讓 Impala 基于每一個表的大小、每一個列不同值的個數、等等資訊自動的優化查詢。COMPUTE STATS 語句和 連接配接優化(join optimization)是 Impala 1.2.2 引入的新功能。為了保證每個表上統計資訊的精确,請在表加載資料之後執行 COMPUTE STATS 語句,并在因 INSERT, LOAD DATA, 添加分區等操作導緻資料大幅變化之後再次執行。
假如連接配接查詢中所有表的統計資訊不可用,或 Impala 選擇的連接配接順序不是最優,你可以通過在 SELECT 關鍵字之後立刻緊跟 STRAIGHT_JOIN 關鍵字,來覆寫自動的連接配接順序優化。這時候,Impala 使用表在查詢中出現的順序來指導連接配接如何處理。首先是最大的表,然後是次大的,依此類推。術語"最大"和"最小"指中間結果集的大小,這些基于作為結果集一部分的每個表的行數和列數(The terms "largest" and "smallest" refers to the size of the intermediate result set based on the number of rows and columns from each table that are part of the result set)。例如,如果你連接配接了表 sales 和 customers,查詢可能是從産生了 5000 次購買的 100 個使用者中查找結果集。這時候,你應該使用 SELECT ... FROM sales JOIN customers ..., 把 customers 放在右側,因為在這個查詢上下文中它更小。
依賴于表的絕對和相對的大小,Impala 查詢計劃器在執行連接配接查詢的不同技術之間進行選擇。廣播連接配接(Broadcast joins) 是預設方式,右側的表被認為比左側的表小,并且它的内容被發送到查詢涉及到的其他節點上。替代的技術稱作分割連接配接(partitioned join) (與分區表無關),更适用于近乎相同大小的大型表的連接配接。使用這一技術,每一個表的部分内容被發送到對應的其他節點,然後這些行的子集可以并行處理。廣播和分區連接配接的選擇仍然依賴于連接配接中所有表的可用的、使用 COMPUTE STATS 語句手機的統計資訊。
對查詢執行 EXPLAIN 語句,檢視該查詢采用了哪種連接配接政策。如果你發現一個查詢使用了廣播連接配接,而你通過基準測試知道分割連接配接更高效,或者相反情況時,在查詢上添加提示指定使用的精确的連接配接機制。參見 Hints 了解詳細資訊。
統計資訊不可用時連接配接如何處理
假如連接配接中的一些表的表或列統計資訊不可用,Impala 仍然使用可用的那部分資訊重新排清單,包含可用統計資訊的表放在連接配接的左側,按照整體大小和基數降序排列(Tables with statistics are placed on the left side of the join order, in descending order of cost based on overall size and cardinality)。沒有統計資訊的表被認為大小為 0,也就是說,它們總是放置在連接配接查詢的右側。
Overriding Join Reordering with STRAIGHT_JOIN
假如因為過時的統計資訊或意外的資料分布, Impala 連接配接查詢很低效,你可以通過在 SELECT 關鍵字之後緊跟着 STRAIGHT_JOIN 關鍵字來重新排序連接配接的表,使的 Impala 高效。STRAIGHT_JOIN 關鍵字關閉 Impala 内部使用的連接配接子句的重新排序,并根據 查詢中 join 子句中列出的順序優化(The STRAIGHT_JOIN keyword turns off the reordering of join clauses that Impala does internally, and produces a plan that relies on the join clauses being ordered optimally in the query text)。這時,重寫查詢以便最大的表在最左側,跟着是次大的,依此類推直到最小的表放在最右側。
在下面的例子裡,基于 BIG 表的子查詢産生一個非常小的結果集,但是這個表仍被視為好像它是最大的并放置在連接配接順序的第一位。為最後的連接配接子句使用 STRAIGHT_JOIN 關鍵字,防止最終的表重新排序,保持它作為最右邊表的連接配接順序(Using STRAIGHT_JOIN for the last join clause prevents the final table from being reordered, keeping it as the rightmost table in the join order)。
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;
Examples of Join Order Optimization
下面的例子示範了10億、2億、1百萬行表之間的連接配接(這時,表都是未分區的,使用 Parquet 格式)。最小的表是最大的表的一個子集,友善起見在唯一的 ID 列上進行連接配接。最小的表隻包含其他表中列的一個子集。
[localhost:21000] > create table big stored as parquet as select * from raw_data;
+----------------------------+
| summary |
+----------------------------+
| Inserted 1000000000 row(s) |
+----------------------------+
Returned 1 row(s) in 671.56s
[localhost:21000] > desc big;
+-----------+---------+---------+
| name | type | comment |
+-----------+---------+---------+
| id | int | |
| val | int | |
| zfill | string | |
| name | string | |
| assertion | boolean | |
+-----------+---------+---------+
Returned 5 row(s) in 0.01s
[localhost:21000] > create table medium stored as parquet as select * from big limit 200 * floor(1e6);
+---------------------------+
| summary |
+---------------------------+
| Inserted 200000000 row(s) |
+---------------------------+
Returned 1 row(s) in 138.31s
[localhost:21000] > create table small stored as parquet as select id,val,name from big where assertion = true limit 1 * floor(1e6);
+-------------------------+
| summary |
+-------------------------+
| Inserted 1000000 row(s) |
+-------------------------+
Returned 1 row(s) in 6.32s
對于任意類型的性能測試,使用 EXPLAIN 語句檢視将執行的查詢是如何的昂貴(expensive)而不需要實際運作它,并且啟用詳細的 EXPLAIN 計劃包含更詳細的性能導向的資訊:最有趣的計劃行---展示了沒有統計資訊的連接配接的表--以黑體突出,Impala 無法正确的估算處理的每個階段中涉及的行數,通常采用廣播連接配接機制把其中之一的表的完整資料發送到各個節點上(Impala cannot make a good estimate of the number of rows involved at each stage of processing,and is likely to stick with the BROADCAST join mechanism that sends a complete copy of one of the tables to each node)。
[localhost:21000] > set explain_level=verbose;
EXPLAIN_LEVEL set to verbose
[localhost:21000] > explain select count(*) from big join medium where big.id = medium.id;
+----------------------------------------------------------+
| Explain String |
+----------------------------------------------------------+
| Estimated Per-Host Requirements: Memory=2.10GB VCores=2 |
| |
| PLAN FRAGMENT 0 |
| PARTITION: UNPARTITIONED |
| |
| 6:AGGREGATE (merge finalize) |
| | output: SUM(COUNT(*)) |
| | cardinality: 1 |
| | per-host memory: unavailable |
| | tuple ids: 2 |
| | |
| 5:EXCHANGE |
| cardinality: 1 |
| per-host memory: unavailable |
| tuple ids: 2 |
| |
| PLAN FRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 5 |
| UNPARTITIONED |
| |
| 3:AGGREGATE |
| | output: COUNT(*) |
| | cardinality: 1 |
| | per-host memory: 10.00MB |
| | tuple ids: 2 |
| | |
| 2:HASH JOIN | | | join op: INNER JOIN (BROADCAST) | | | hash predicates: |
| | big.id = medium.id | | | cardinality: unavailable | | | per-host memory: 2.00GB |
| | tuple ids: 0 1 |
| | |
| |----4:EXCHANGE |
| | cardinality: unavailable |
| | per-host memory: 0B |
| | tuple ids: 1 |
| | |
| 0:SCAN HDFS | | table=join_order.big #partitions=1/1 size=23.12GB |
| table stats: unavailable |
| column stats: unavailable |
| cardinality: unavailable | | per-host memory: 88.00MB |
| tuple ids: 0 |
| |
| PLAN FRAGMENT 2 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 4 |
| UNPARTITIONED |
| |
| 1:SCAN HDFS | | table=join_order.medium #partitions=1/1 size=4.62GB |
| table stats: unavailable |
| column stats: unavailable |
| cardinality: unavailable | | per-host memory: 88.00MB |
| tuple ids: 1 |
+----------------------------------------------------------+
Returned 64 row(s) in 0.04s
采集所有表的統計資訊很簡單,在每一個表上執行 COMPUTE STATS 語句:
[localhost:21000] > compute stats small;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 3 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 4.26s
[localhost:21000] > compute stats medium;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 5 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 42.11s
[localhost:21000] > compute stats big;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 5 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 165.44s
有了統計資訊,Impala 可以選擇更有效的連接配接順序而不是按照查詢中從左到右各個表的順序,并且可以基于表的大小和行數選擇廣播連接配接或分割連接配接政策:
[localhost:21000] > explain select count(*) from medium join big where big.id = medium.id;
Query: explain select count(*) from medium join big where big.id = medium.id
+-----------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------+
| Estimated Per-Host Requirements: Memory=937.23MB VCores=2 |
| |
| PLAN FRAGMENT 0 |
| PARTITION: UNPARTITIONED |
| |
| 6:AGGREGATE (merge finalize) |
| | output: SUM(COUNT(*)) |
| | cardinality: 1 |
| | per-host memory: unavailable |
| | tuple ids: 2 |
| | |
| 5:EXCHANGE |
| cardinality: 1 |
| per-host memory: unavailable |
| tuple ids: 2 |
| |
| PLAN FRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 5 |
| UNPARTITIONED |
| |
| 3:AGGREGATE |
| | output: COUNT(*) |
| | cardinality: 1 |
| | per-host memory: 10.00MB |
| | tuple ids: 2 |
| | |
| 2:HASH JOIN |
| | join op: INNER JOIN (BROADCAST) |
| | hash predicates: |
| | big.id = medium.id |
| | cardinality: 1443004441 |
| | per-host memory: 839.23MB |
| | tuple ids: 1 0 |
| | |
| |----4:EXCHANGE |
| | cardinality: 200000000 |
| | per-host memory: 0B |
| | tuple ids: 0 |
| | |
| 1:SCAN HDFS |
| table=join_order.big #partitions=1/1 size=23.12GB |
| table stats: 1000000000 rows total |
| column stats: all |
| cardinality: 1000000000 |
| per-host memory: 88.00MB |
| tuple ids: 1 |
| |
| PLAN FRAGMENT 2 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 4 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=join_order.medium #partitions=1/1 size=4.62GB |
| table stats: 200000000 rows total |
| column stats: all |
| cardinality: 200000000 |
| per-host memory: 88.00MB |
| tuple ids: 0 |
+-----------------------------------------------------------+
Returned 64 row(s) in 0.04s
[localhost:21000] > explain select count(*) from small join big where big.id = small.id;
Query: explain select count(*) from small join big where big.id = small.id
+-----------------------------------------------------------+
| Explain String |
+-----------------------------------------------------------+
| Estimated Per-Host Requirements: Memory=101.15MB VCores=2 |
| |
| PLAN FRAGMENT 0 |
| PARTITION: UNPARTITIONED |
| |
| 6:AGGREGATE (merge finalize) |
| | output: SUM(COUNT(*)) |
| | cardinality: 1 |
| | per-host memory: unavailable |
| | tuple ids: 2 |
| | |
| 5:EXCHANGE |
| cardinality: 1 |
| per-host memory: unavailable |
| tuple ids: 2 |
| |
| PLAN FRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 5 |
| UNPARTITIONED |
| |
| 3:AGGREGATE |
| | output: COUNT(*) |
| | cardinality: 1 |
| | per-host memory: 10.00MB |
| | tuple ids: 2 |
| | |
| 2:HASH JOIN |
| | join op: INNER JOIN (BROADCAST) |
| | hash predicates: |
| | big.id = small.id |
| | cardinality: 1000000000 |
| | per-host memory: 3.15MB |
| | tuple ids: 1 0 |
| | |
| |----4:EXCHANGE |
| | cardinality: 1000000 |
| | per-host memory: 0B |
| | tuple ids: 0 |
| | |
| 1:SCAN HDFS |
| table=join_order.big #partitions=1/1 size=23.12GB |
| table stats: 1000000000 rows total |
| column stats: all |
| cardinality: 1000000000 |
| per-host memory: 88.00MB |
| tuple ids: 1 |
| |
| PLAN FRAGMENT 2 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 4 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=join_order.small #partitions=1/1 size=17.93MB |
| table stats: 1000000 rows total |
| column stats: all |
| cardinality: 1000000 |
| per-host memory: 32.00MB |
| tuple ids: 0 |
+-----------------------------------------------------------+
Returned 64 row(s) in 0.03s
當類似這些的查詢實際運作時,執行時間是相對固定的,不管查詢語句中表的順序如何。下面的例子使用了唯一的 ID 列和包含重複值的 VAL 列:
[localhost:21000] > select count(*) from big join small on (big.id = small.id);
Query: select count(*) from big join small on (big.id = small.id)
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
Returned 1 row(s) in 21.68s
[localhost:21000] > select count(*) from small join big on (big.id = small.id);
Query: select count(*) from small join big on (big.id = small.id)
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
Returned 1 row(s) in 20.45s
[localhost:21000] > select count(*) from big join small on (big.val = small.val);
+------------+
| count(*) |
+------------+
| 2000948962 |
+------------+
Returned 1 row(s) in 108.85s
[localhost:21000] > select count(*) from small join big on (big.val = small.val);
+------------+
| count(*) |
+------------+
| 2000948962 |
+------------+
Returned 1 row(s) in 100.76s

: 當檢測連接配接查詢的性能和連接配接順序優化的有效性時,請確定查詢涉及到足夠的資料和叢集資源,以便能在查詢計劃中看出不同。例如,隻有幾兆大小的單個資料檔案将會存放在一個 HDFS 塊裡,并隻被單個節點處理。同樣的,假如你使用單節點或兩個節點的叢集,廣播連接配接和分割連接配接政策的效率可能沒什麼分别。
Impala 如何使用統計資訊進行查詢優化
當統計資訊可用時,Impala 可以更好的優化複雜的或多表查詢,可以更好地了解資料量和值的分布,并使用這些資訊幫助查詢并行處理和分布負載。下面的章節描述了 Impala 可以使用的統計資訊的分類,以及如何産生這些資訊并保持最新。
原來 Impala 依靠 Hive 采集統計資訊的機制,通過 Hive ANALYZE TABLE 語句初始化一個 MapReduce 作業進行。為了更好的性能、使用者友好性和可靠性, 在 1.2.1 之後,Impala 實作了自己的 COMPUTE STATS 語句,以及相關的 SHOW TABLE STATS 和 SHOW COLUMN STATS 語句。
表統計資訊
當 metastore 資料庫中的中繼資料可用時,Impala 查詢計劃器可以使用整個表和分區的統計資訊。這些中繼資料用于本表的某些優化,并和列統計資訊組合用于其他優化。
當向表或分區加載資料加載資料後,使用以下技術之一采集表的統計資訊:
- 在 Impala 中執行 COMPUTE STATS 語句。這一在 Impala 1.2.2 新引入的語句是首選方法,因為:
- 它在單個操作中采集表、表的所有分區和所有列的統計資訊
- 它不依賴于任意特殊的 Hive 設定、 metastore 配置、或單獨的資料庫來存放統計資訊
- 它使用 Impala 查詢基礎架構來計算行數、不同值個數等等,通常比用 Hive ANALYZE TABLE statement.
- 當 Hive 中設定 hive.stats.autogather 為啟用時,通過 Hive INSERT OVERWRITE 語句加載資料
- 為整個表或特定分區在 Hive 中執行 ANALYZE TABLE 語句:
例如,為非分區表采集統計資訊:ANALYZE TABLEtablename[PARTITION(partcol1[=val1],partcol2[=val2], ...)] COMPUTE STATISTICS [NOSCAN];
為以 state 和 city 分區列的分區表 store 表采集所有分區的統計資訊:ANALYZE TABLE customer COMPUTE STATISTICS;
隻采集分區表 store 中 California 分區的統計資訊:ANALYZE TABLE store PARTITION(s_state, s_county) COMPUTE STATISTICS;
ANALYZE TABLE store PARTITION(s_state='CA', s_county) COMPUTE STATISTICS;
使用 SHOW TABLE STATS table_name 語句,檢視表的統計資訊是否可用,以及統計資訊的詳細内容。參考 SHOW Statement 了解詳細資訊。
假如你使用基于 Hive 的方法采集統計資訊,參見 the Hive wiki 了解關于 Hive 的配置要求。 Cloudera 推薦使用 Impala COMPUTE STATS 語句以避免 Hive 采集統計資訊程式潛在的配置和可擴充性方面的問題。
列統計資訊
當 metastore 資料庫中的中繼資料可用時,Impala 查詢計劃器可以使用單個列的統計資訊。這一技術對于比較連接配接查詢中所有表的連接配接列,以幫助評估查詢中每一個表将傳回多少行最有價值。目前 Impala 自身不會自動建立這些中繼資料。使用 Hive 中的 ANALYZE TABLE 語句收集這些統計資訊(無論表是在 Impala 還是 Hive 中建立的,這一語句都可以正常工作)。

:Impala 中列統計資訊很重要,但是對于應用表,你也同樣需要表的統計資訊,像在 表統計資訊 中描述的那樣。假如你使用 Impala COMPUTE STATS 語句,表和表中所有列的統計資訊都會自動同時收集。
對于特定的一組列,使用 SHOW COLUMN STATS table_name 語句檢查列統計資訊是否可用,或檢查針對引用這系列的表的查詢的擴充的 EXPLAIN 輸出。參見 SHOW 語句 和 EXPLAIN 語句了解詳細資訊。
通過 ALTER TABLE 手工設定統計資訊
所有統計資訊中最關鍵的部分是表(未分區的表)或分區(分區表)中的行數。COMPUTE STATS 語句總是采集所有列的統計資訊以及整個表的統計資訊。假如在添加了一個分區或插入資料之後,進行完整的 COMPUTE STATS 操作實際不可行時,或者當行數不同時,可以預見 Impala 将産生更好的執行計劃時,你可以通過 ALTER TABLE 語句手工設定行數:
create table analysis_data stored as parquet as select * from raw_data;
Inserted 1000000000 rows in 181.98s
compute stats analysis_data;
insert into analysis_data select * from smaller_table_we_forgot_before;
Inserted 1000000 rows in 15.32s
-- 現在表裡共有 1001000000 行。我們可以更新統計資訊中的這一個資料點
alter table analysis_data set tblproperties('numRows'='1001000000');
對于分區表,同時更新每一個分區的行數和整個表的行數:
-- 如果原來表中包含 1000000 行,我們新添加了一個分區
-- 修改該分區和整個表的 numRows 屬性
alter table partitioned_data partition(year=2009, month=4) set tblproperties ('numRows'='30000');
alter table partitioned_data set tblproperties ('numRows'='1030000');
實際上,COMPUTE STATS 語句已經夠快了,這一技術是不必要的。這一方法最大的價值就是可以調整 numRows 值的大小來産生理想的連接配接順序進而解決性能問題(It is most useful as a workaround for in case of performance issues where you might adjust the numRowsvalue higher or lower to produce the ideal join order)。
在 Impala 使用表和列統計資訊的例子
下面的例子通過一系列的 SHOW TABLE STATS, SHOW COLUMN STATS, ALTER TABLE, SELECT , INSERT 語句來示範了 Impala 如何使用統計資訊幫助優化查詢的各個方面。
這一例子展示了 STORE 表的表和列的統計資訊,這個表使用的是 TPC-DS 決策支援系統基準測試中的表。這是一個隻有 12 行資料的小表。最初,在使用 COMPUTE STATS 采集統計資訊之前,大多數數字列顯示占位符 -1,表示這一數字是未知的。這一待填充的數值是容易在實體層計量或推斷出的,如檔案個數,檔案的總資料大小,以及對具有固定大小如 INT,FLOAT,TIMESTAMP 等資料類型的最大和平均大小(The figures that are filled in are values that are easily countable or deducible at the physical level, such as the number of files, total data size of the files, and the maximum and average sizes for data types that have a constant size such as INT, FLOAT, and TIMESTAMP)。
[localhost:21000] > show table stats store;
+-------+--------+--------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+--------+--------+
| -1 | 1 | 3.08KB | TEXT |
+-------+--------+--------+--------+
Returned 1 row(s) in 0.03s
[localhost:21000] > show column stats store;
+--------------------+-----------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------------------+-----------+------------------+--------+----------+----------+
| s_store_sk | INT | -1 | -1 | 4 | 4 |
| s_store_id | STRING | -1 | -1 | -1 | -1 |
| s_rec_start_date | TIMESTAMP | -1 | -1 | 16 | 16 |
| s_rec_end_date | TIMESTAMP | -1 | -1 | 16 | 16 |
| s_closed_date_sk | INT | -1 | -1 | 4 | 4 |
| s_store_name | STRING | -1 | -1 | -1 | -1 |
| s_number_employees | INT | -1 | -1 | 4 | 4 |
| s_floor_space | INT | -1 | -1 | 4 | 4 |
| s_hours | STRING | -1 | -1 | -1 | -1 |
| s_manager | STRING | -1 | -1 | -1 | -1 |
| s_market_id | INT | -1 | -1 | 4 | 4 |
| s_geography_class | STRING | -1 | -1 | -1 | -1 |
| s_market_desc | STRING | -1 | -1 | -1 | -1 |
| s_market_manager | STRING | -1 | -1 | -1 | -1 |
| s_division_id | INT | -1 | -1 | 4 | 4 |
| s_division_name | STRING | -1 | -1 | -1 | -1 |
| s_company_id | INT | -1 | -1 | 4 | 4 |
| s_company_name | STRING | -1 | -1 | -1 | -1 |
| s_street_number | STRING | -1 | -1 | -1 | -1 |
| s_street_name | STRING | -1 | -1 | -1 | -1 |
| s_street_type | STRING | -1 | -1 | -1 | -1 |
| s_suite_number | STRING | -1 | -1 | -1 | -1 |
| s_city | STRING | -1 | -1 | -1 | -1 |
| s_county | STRING | -1 | -1 | -1 | -1 |
| s_state | STRING | -1 | -1 | -1 | -1 |
| s_zip | STRING | -1 | -1 | -1 | -1 |
| s_country | STRING | -1 | -1 | -1 | -1 |
| s_gmt_offset | FLOAT | -1 | -1 | 4 | 4 |
| s_tax_precentage | FLOAT | -1 | -1 | 4 | 4 |
+--------------------+-----------+------------------+--------+----------+----------+
Returned 29 row(s) in 0.04s
使用 Hive ANALYZE TABLE 語句采集列的統計資訊,你必須指定要采集統計資訊的每一個列。而 Impala COMPUTE STATS 語句自動采集所有列的統計資訊,因為它較快的讀取整個表并高效的計算所有列的值。下面例子展示了執行 COMPUTE STATS 語句之後,表和所有列的統計資訊都被填充:
[localhost:21000] > compute stats store;
+------------------------------------------+
| summary |
+------------------------------------------+
| Updated 1 partition(s) and 29 column(s). |
+------------------------------------------+
Returned 1 row(s) in 1.88s
[localhost:21000] > show table stats store;
+-------+--------+--------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+--------+--------+
| 12 | 1 | 3.08KB | TEXT |
+-------+--------+--------+--------+
Returned 1 row(s) in 0.02s
[localhost:21000] > show column stats store;
+--------------------+-----------+------------------+--------+----------+-------------------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------------------+-----------+------------------+--------+----------+-------------------+
| s_store_sk | INT | 12 | 0 | 4 | 4 |
| s_store_id | STRING | 6 | 0 | 16 | 16 |
| s_rec_start_date | TIMESTAMP | 4 | 0 | 16 | 16 |
| s_rec_end_date | TIMESTAMP | 3 | 6 | 16 | 16 |
| s_closed_date_sk | INT | 3 | 9 | 4 | 4 |
| s_store_name | STRING | 8 | 0 | 5 | 4.25 |
| s_number_employees | INT | 9 | 0 | 4 | 4 |
| s_floor_space | INT | 10 | 0 | 4 | 4 |
| s_hours | STRING | 2 | 0 | 8 | 7.083300113677979 |
| s_manager | STRING | 7 | 0 | 15 | 12 |
| s_market_id | INT | 7 | 0 | 4 | 4 |
| s_geography_class | STRING | 1 | 0 | 7 | 7 |
| s_market_desc | STRING | 10 | 0 | 94 | 55.5 |
| s_market_manager | STRING | 7 | 0 | 16 | 14 |
| s_division_id | INT | 1 | 0 | 4 | 4 |
| s_division_name | STRING | 1 | 0 | 7 | 7 |
| s_company_id | INT | 1 | 0 | 4 | 4 |
| s_company_name | STRING | 1 | 0 | 7 | 7 |
| s_street_number | STRING | 9 | 0 | 3 | 2.833300113677979 |
| s_street_name | STRING | 12 | 0 | 11 | 6.583300113677979 |
| s_street_type | STRING | 8 | 0 | 9 | 4.833300113677979 |
| s_suite_number | STRING | 11 | 0 | 9 | 8.25 |
| s_city | STRING | 2 | 0 | 8 | 6.5 |
| s_county | STRING | 1 | 0 | 17 | 17 |
| s_state | STRING | 1 | 0 | 2 | 2 |
| s_zip | STRING | 2 | 0 | 5 | 5 |
| s_country | STRING | 1 | 0 | 13 | 13 |
| s_gmt_offset | FLOAT | 1 | 0 | 4 | 4 |
| s_tax_precentage | FLOAT | 5 | 0 | 4 | 4 |
+--------------------+-----------+------------------+--------+----------+-------------------+
Returned 29 row(s) in 0.04s
下面的例子展示了分區表中統計資訊如何表示。這時,我們設定了一個存放世界上最瑣碎的戶籍資料的表,包含一個 STRING 字段,根據 YEAR 列進行分區。表統計資訊中每一個分區都包含一個單獨的實體,再加上最終的總數。對于分區列,列統計資訊中包含一些容易推斷的事實,如不同值的個數(分區子目錄的個數) 和 NULL 值的個數(分區列中不可能出現)。
localhost:21000] > describe census;
+------+----------+---------+
| name | type | comment |
+------+----------+---------+
| name | string | |
| year | smallint | |
+------+----------+---------+
Returned 2 row(s) in 0.02s
[localhost:21000] > show table stats census;
+-------+-------+--------+------+---------+
| year | #Rows | #Files | Size | Format |
+-------+-------+--------+------+---------+
| 2000 | -1 | 0 | 0B | TEXT |
| 2004 | -1 | 0 | 0B | TEXT |
| 2008 | -1 | 0 | 0B | TEXT |
| 2010 | -1 | 0 | 0B | TEXT |
| 2011 | 0 | 1 | 22B | TEXT |
| 2012 | -1 | 1 | 22B | TEXT |
| 2013 | -1 | 1 | 231B | PARQUET |
| Total | 0 | 3 | 275B | |
+-------+-------+--------+------+---------+
Returned 8 row(s) in 0.02s
[localhost:21000] > show column stats census;
+--------+----------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+----------+------------------+--------+----------+----------+
| name | STRING | -1 | -1 | -1 | -1 |
| year | SMALLINT | 7 | 0 | 2 | 2 |
+--------+----------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.02s
下面的例子示範了在 Impala 中執行 COMPUTE STATS 語句後統計資訊是如何填充的。
[localhost:21000] > compute stats census;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 3 partition(s) and 1 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 2.16s
[localhost:21000] > show table stats census;
+-------+-------+--------+------+---------+
| year | #Rows | #Files | Size | Format |
+-------+-------+--------+------+---------+
| 2000 | -1 | 0 | 0B | TEXT |
| 2004 | -1 | 0 | 0B | TEXT |
| 2008 | -1 | 0 | 0B | TEXT |
| 2010 | -1 | 0 | 0B | TEXT |
| 2011 | 4 | 1 | 22B | TEXT |
| 2012 | 4 | 1 | 22B | TEXT |
| 2013 | 1 | 1 | 231B | PARQUET |
| Total | 9 | 3 | 275B | |
+-------+-------+--------+------+---------+
Returned 8 row(s) in 0.02s
[localhost:21000] > show column stats census;
+--------+----------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+----------+------------------+--------+----------+----------+
| name | STRING | 4 | 1 | 5 | 4.5 |
| year | SMALLINT | 7 | 0 | 2 | 2 |
+--------+----------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.02s
關于在統計資訊可用時,示範一些查詢工作方式不同的例子,參見 Examples of Join Order Optimization。在采集統計資訊之前和之後,觀察 EXPLAIN 的輸出,你可以看到 Impala 使用不同方式執行同一個查詢。對比之前和之後的查詢時間,檢查之前和之後 PROFILE 輸出的吞吐量的值, to verify how much the improved plan speeds up performance.
Impala 查詢基準測試
與其他 Hadoop 元件類似,因為 Impala 是設計用來處理分布式環境中大量資料的,是以應使用真實的資料和叢集配置進行性能測試。使用多節點的叢集而不是單節點的;對包含 TB 資料的表進行查詢而不是幾十G的。Impala 所有使用的并行處理技術最适合用于超出了單個伺服器容量的負載。
當你執行查詢傳回大量的行,列印輸出結果所花費的 CPU 時間是巨大的,為實際查詢時間添加了不準确的度量(the CPU time to pretty-print the output can be substantial, giving an inaccurate measurement of the actual query time)。請考慮在 impala-設立了 指令中使用 -B 選項關閉列印結果,而可選的 -o 選項可以儲存查詢結果到一個檔案而不是列印到螢幕上。參見 impala-shell Command-Line Options 了解詳細資訊。
控制資源使用
通過為 impalad 守護程序指定 -mem_limits 選項,你可以限制查詢執行時 Impala 使用的記憶體量。參見 Modifying Impala Startup Options 了解詳細資訊。這一限制僅對查詢直接消耗的記憶體有效;Impala 在啟動時保留了額外的記憶體,例如用于緩存中繼資料。
對于生産部署,Cloudera 推薦使用如 cgroups 機制實作資源隔離,可以在 Cloudera Manager 中配置。參見 Managing Clusters with Cloudera Manager 了解詳細資訊。
當你結合 CDH 5 使用 Impala 時,你可以像在 Using Resource Management with Impala (CDH 5 Only) 中描述的那樣使用 YARN 資源管理架構。目前 CDH 5 仍是 beta 版;用于 CDH 5 beta 版的對應 Impala 版本是 1.2.0。
了解 EXPLAIN 計劃
EXPLAIN 語句提供查詢将要執行的邏輯步驟的大綱,例如工作在節點之間如何分布,以及中間結果如何組合産生最終結果集。你可以在實際執行查詢之前看到這些詳細資訊。你可以使用這些資訊來檢查查詢是否使用一些非常意外的或低效的方式執行。
在查詢 profile 報告的開始部分,EXPLAIN 計劃同樣被列印出來,以便于檢查查詢的邏輯和實體的各個方面。
EXPLAIN 輸出的細節的數量由 EXPLAIN_LEVEL 查詢選項控制。當性能調整時複核表和列的統計資訊時,或與 CDH5 中資源管理功能聯合評估查詢資源使用情況時(or when estimating query resource usage in conjunction with the resource management features in CDH 5),通常從 normal 修改為 verbose (或 0 到 1)。
了解查詢 Profile
PROFILE 語句在 impala-shell 中可用,産生一個最近執行語句的詳細的底層報告。 不像在 Understanding the EXPLAIN Plan 中描述的 EXPLAIN 那樣,這一資訊僅當查詢執行完成後可用。它展示了實體細節如每一節點讀取的位元組數,最大記憶體使用等等資訊。你可以使用這些資訊确定查詢是 I/O 密集(I/O-bound)還是 CPU 密集(CPU-bound),是否一些網絡條件達到瓶頸,是否一台放緩影響到了部分節點而不影響另一部分(whether a slowdown is affecting some nodes but not others),并檢查推薦配置如 short-circuit local reads 是否生效。
EXPLAIN plan 同樣被列印在查詢 profile 報告的開始,以便于檢查查詢的邏輯和實體的各個方面。在 EXPLAIN_LEVEL 中描述的 EXPLAIN_LEVEL 查詢選項,同樣對控制 PROFILE 指令中産生的 EXPLAIN 輸出列印的詳細程度有效。
測試 Impala 性能
測試以確定 Impala 為性能進行了最優配置。假如你沒有使用 Cloudera Manager 安裝的 Impala,完成本主題中描述的内容以幫助确認已經合适的配置。即使你使用 Cloudera Manager 安裝的 Impala,已經自動應用合适的配置,這一過程可以檢驗 Impala 設定是否正确。
檢查 Impala 配置值
你可以使用浏覽器連接配接到 Impala 伺服器檢查 Impala 的配置值:
檢查 Impala 配置值:
- 使用浏覽器連接配接到你的環境中運作 impalad 程序的主機之一。使用類似格式連接配接 http://hostname:port/varz Note : 在前面的例子中,替換 hostname 和 port 為你的 Impala 的名稱和端口。預設端口是 25000
Impala 性能調整(翻譯) Impala 性能調整 -
檢視已配置的值
例如,檢查你的系統是否啟用了本地塊跟蹤資訊(block locality tracking information),應檢查 dfs.datanode.hdfs-blocks-metadata.enabled 的值是否為 true
檢查資料本地化(data locality):
- 在多個節點上都可用的資料集上執行查詢。例如,對具有合理機會傳播到多個資料節點上表 MyTable 進行查詢:
[impalad-host:21000] > SELECT COUNT (*) FROM MyTable
- 當查詢完成後,檢查 Impala 日志的記憶體。你可能會發現類似下面的消息:
Total remote scan volume = 0
遠端掃描的存在辨別 impalad 沒有運作在正确的節點上。當一些資料節點上沒有運作 impalad 或無法運作,因為啟動查詢的 impalad 執行個體無法連接配接到一個或多個 impalad 執行個體(This can be because some DataNodes do not have impalad running or it can be because the impalad instance that is starting the query is unable to contact one or more of the impalad instances)。
了解這些問題的原因:
- 連接配接到調試web伺服器。預設的,伺服器運作在 25000 端口。這一頁面列出了你叢集中所有在運作的 impalad 執行個體。假如列出的執行個體少于你的預期,這通常表明一些 DataNode 沒有運作 impalad。請確定所有 DataNode 都啟動了 impalad
- 假如你使用多宿主(multi-homed)主機,請確定 Impala 守護程序的主機名解析到運作的 impalad(If you are using multi-homed hosts, ensure that the Impala daemon's hostname resolves to the interface on which impalad is running)。Impala 在啟動 impalad 時顯示主機名。假如需要明确設定主機名,請使用 --hostname 标志
- 檢查 statestored 是否正常運作。複查 state store 日志的内容以確定所有的 impalad 執行個體别列為連接配接到 state store
複查 Impala 日志
你可以複查 Impala 日志的内容,查找短路讀取(short-circuit reads)或塊本地跟蹤(block location tracking)沒有正常運作的标志。在檢查日志之前,對一個小的 HDFS 資料集執行一個簡單的查詢。完成一個查詢任務使用目前設定産生日志資訊。啟動 Impala 和執行查詢的資訊可以在 Starting Impala 和 Using the Impala Shell 找到。登入資訊可以在 Using Impala Logging 中找到。日志資訊和對應的描述如下:
Log Message | Interpretation |
---|---|
| Tracking block locality 未啟用 |
| Native checksumming 未啟用 |
版權聲明:本文為CSDN部落客「weixin_33700350」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_33700350/article/details/92510553