一、分区表
二、Join查询调优
优化连接查询最简单的方式是使用compute stats命令收集所有参与关联表的统计信息,让impala根据每个表的大小、列的非重复值个数等相关信息自动优化查询。
如果参与关联的表的统计信息不可用,使用impala自动的连接顺序效率很低,可以在select关键字后使用straight_join关键字手动指定连接顺序,指定了该关键字之后,impala会使用表在查询中出现的先后顺序作为关联顺序进行处理。
使用straight_join关键字需要手动指定连接表的先后顺序:
(1)指定最大的表为第一张表。
(2)指定最小的一张表作为下一张表。
(3)接着指定剩下的表中最小的表作为下一张表。如果有四张表分别为BIG
, MEDIUM
, SMALL
, 和TINY
, 指定的顺序应该为BIG
, TINY
, SMALL
, MEDIUM
.
Impala查询优化器根据表的绝对大小和相对大小而选择不同的关联技术:
(1)默认的方式为Broadcast joins,当大表连接小表时,小表的内容会被发送到所有执行查询的节点上
(2)另一种为partitioned join,用于大小差不多的大表关联,使用此方式,可以保证关联操作可以并行执行,每个表的一部分数据被发送到不同的节点上,最后各个节点分别对传送过来的数据并行处理。具体使用哪种方式依赖于compute stats的统计信息。
可以使用特定的查询执行explain语句,来确定表的连接策略,如果通过基准测试发现某种策略优于另外一种策略,那么可以通过Hint的方式手动指定需要的连接方式。
1.当统计信息不可用时如何处理join
如果只有某些表的统计信息不可用,impala会根据存在统计信息的表重新生成连接顺序,有统计信息的表会被放在连接顺序的最左端,并根据表的基数和规模降序排列,没有统计信息的表会被作为空表对待,总是放在连接顺序的最右边。
2.使用straight_join覆盖连接顺序
如果关联查询由于统计信息过期或者数据分布等问题导致效率低下,可以通过straight_join关键字改变连接顺序,指定顺序后不会再使用impala自动生成的连接顺序。
3.案例
[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查看连接信息,启用执行计划的详细输出,可以看到更多的性能相关的输出信息,红色字体显示。信息提示参与关联的表没有统计信息,impala不能为每个执行阶段估计出结果集的大小,使用Broadcast方式向每个节点发送一个表的完整副本。
[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 |