1. Hadoop-Impala优化十大指导原则和最佳实践
以下是性能准则和最佳做法。您可以使用在规划过程中实验,和hadoop集群一起进行impala的性能调整。所有这些信息也可在文档的其他地方更详细的impala文档;以下是优化的方法措施,强调优化调优技术提供最高的投资回报
1)选择适当的数据文件格式
2)避免数据摄入过程,产生许多小的文件
3)基于实际数据量选择分区粒度
4)使用最小的适当的整数类型进行分区键列
5)选择一个合适的block大小
6)收集性能关键或高容量连接查询中使用的所有表的统计数据
7)尽量减少将结果发送给客户端的开销
8)请确认您的查询以一种有效的逻辑方式进行计划
9)验证查询的性能特征
10)使用适当的操作系统设置
1.1. 选择适当的数据文件格式
通常,对于大量的数据(每个表或分区有很多G字节),Parquet文件格式表现最好,因其列式存储布局相结合,大量的I/O请求的大小,和压缩编码。
看到Impala与所有支持的文件格式的Impala对比Hadoop文件格式,并采用Parquet文文件格式的详细说明,Parquet表
对于小容量的数据,几个字节或更少的每个表或分区,你可能看不到的文件格式之间的业绩差异明显。在小数据量,减少I/O的高效的压缩文件格式可以被并行执行的机会减少。当规划一个生产部署或进行基准测试时,总是使用真实的数据卷来获得性能和可扩展性的真实图像。
1.2. 避免摄取过程产生很多年小的文件
避免数据摄入过程,产生许多小的文件。
当生产数据文件以外的impala,喜欢的不是文本格式或公司,在那里你可以通过建立文件排排。一旦数据在Impala,你可以将它转换成更高效的Parquet和分裂成多个数据文件中使用一个单一的插入…SELECT语句。或者,如果你有基础设施,生产多兆字节的文件作为您的地板数据准备过程的一部分,这样做,跳过转换进入impala。
总是使用插入…选择要复制的数据从表到表内大量的impala。避免插入…数据或性能关键表的任何实质性数据量的值,因为每一个这样的语句都会产生一个单独的小数据文件。查看插入的示例的插入语句…选择语法。
例如,如果你在Parquet有成千上万的分区,每个小于256 MB的数据,考虑在一个较低的粒度划分,如由年/月而不是年/月/日。如果一个低效的数据摄取过程产生成千上万的数据文件在同一个表或分区,考虑通过执行一个插入压缩数据…选择将所有数据复制到另一个表;这个过程将被重新组织成一个较小的较大的文件数。
1.3. 选择合适的分区粒度
分区是一种基于一个或多个列的值的物理上划分数据的技术,例如:年、月、日、区域、城市、网站的一部分,等等。当你发出查询请求一个特定的值或值的范围为分区键列,Impala可以避免阅读不相关的数据,可能会产生一个巨大的节省磁盘I / O.
在决定使用哪个列(S)进行分区时,选择合适的粒度级别。例如,你应该分配一年,一个月,一天,或只有一年和一个月?选择一个分区策略,提出至少256 MB的每个分区中的数据,利用HDFS块I/O和Impala分布式查询。
在分区也会导致查询计划需要更长的时间比必要的,如Impala修剪不必要的分区。理想情况下,保持表中的分区的数量低于3万。
准备数据文件时,要在分区目录中,创建几个大文件,而不是许多小文件。如果您以许多小文件的形式接收数据,并没有对输入格式的控制,请考虑使用“插入”…选择语法复制数据从一个表或分区到另一个,它压缩的文件到一个相对小的数量(基于集群中的节点数)。
如果你需要减少分区的整体数量和增加在每个分区的数据量,分区键列,很少引用或非关键查询引用第一次看(不受SLA)。例如,您的网站日志数据可能会被年、月、日和小时划分,但如果大多数查询每天都将结果卷起来,也许你只需要一年、一个月、一天的时间来划分。
如果您需要更大的减少粒度,请考虑创建“桶”,计算对应于不同的分区键的值的计算值。例如,您可以使用trunc()功能与时间戳列组的日期和时间间隔的基础上如周或季度值。看到Impala Date和时间函数的详细信息。
1.4. 使用最小的适当的整数类型进行分区键列
虽然它是使用字符串的分区键列很吸引人,因为这些值可以转化为HDFS的目录名称,但是不管怎样,你可以用普通分区的关键领域如年月数值最小化内存使用,和天。使用最小的整数类型,认为适当的范围值,通常TINYINT为年月日、年和smallint。使用extract()功能拉出个别日期和时间字段的时间戳值,和cast()返回值到相应的整数类型。
1.5. 选择一个合适的数据块大小
默认情况下,插入的Impala…选择语句创建一个256MB的文件块大小的block。(Impala2开始更改变更为默认。从前,限为1 GB,但是Impala关于压缩的保守估计,导致小于1 GB的文件。)
每个parquet文件写的Impala是一个块,让整个文件是由一个单一的主机单元处理。当你拷贝文件到HDFS地板之间或HDFS文件系统,使用hdfs dfs -pb保持原块的大小。
如果只有一个或几个数据块中的表,或在一个分区,是唯一的查询访问,那么你可能会经历一个不同的理由放缓:没有足够的数据来利用Impala的并行分布式查询。每个数据块的一个重要组成部分,由一个单一的核心处理。在16个核心机器的100个节点集群中,您可能同时处理数千个数据文件。您要在“多个小文件”和“单个巨型文件”之间找到一个“小文件”和“单个巨文件”之间的一个“小文件”和“并行处理”之间的“小文件”和“并行处理”。你可以设置parquet_file_size查询选项在插入之前…SELECT语句来减少每个生成的parquet文件的大小。(指定文件大小的字节,一个绝对的数量或在Impala2后,在结束与M为千兆字节。兆字节或G单位)使用不同的文件大小的基准,找到适合您的特定数据量正确的平衡点。
1.6. 收集性能关键或高容量连接查询中使用的所有表的统计数据
用计算统计语句收集统计数据。查看详细信息的连接查询的性能报告。
1.7. 尽量减少将结果发送给客户端的开销
使用技术,如:
汇聚。如果你需要知道一个条件匹配多少行,从一些列的总值中匹配值,最高或最低的匹配,等等,叫汇总等功能count(),sum(),并在查询结果集的max()而不是发送到应用程序和做这些计算有。记住,一个不汇聚的结果集是巨大的,通过网络传输需要大量的时间。
过滤。在查询的其中一个子句中使用所有适用的测试,以消除不相关的行,而不是产生一个大的结果集,并使用应用程序逻辑进行过滤。
限制条款。如果您只需要从结果集上看到一些示例值,或从查询使用顺序的顶部或底部值,包括限制条款,以减少结果集的大小,而不是要求充分的结果集。最好的就是丢掉大多数的行。
避免过度开销。由于漂亮的打印结果并显示在屏幕上。当你检索结果通过使用Impala的外壳,外壳等选项,B和output_delimiter产生结果没有特殊的格式,并将输出重定向到文件中而不是打印到屏幕上。考虑使用插入…选择写的结果直接向HDFS的新文件。看到Impala外壳配置选项的Impala shell的命令行选项的详细信息。
1.8. 请确认您的查询以一种有效的逻辑方式进行计划
在实际运行之前检查一个查询的解释计划。参看性能调整部分的解释声明语句和使用解释计划的细节部分。
1.9. 验证查询的性能特征
验证在运行后,检查查询配置文件的查询配置文件中的低级别的I / O、内存使用、网络带宽、*处理器利用率等方面都在预期的范围内。查看使用查询配置文件进行性能调整的详细信息。
1.10. 使用适当的操作系统设置
看到CDH优化性能有关的操作系统设置的建议,你可以改变影响Impala的性能。特别是,你可能会发现,改变vm.swappiness Linux内核设置一个非零的值(5.7建议为1-10,建议为1,这个参数从早期的为0,5.3的10,目前5.7建议为1,反映一切为最佳实践为依据),提高了系统的整体性能。
2. 分区表优化-8个方法让分区最优化
默认情况下,表中的所有数据文件都位于一个目录中。分区是在加载过程中基于从一个或多个列的值的物理上划分数据的技术,以加快对这些列进行测试的查询。例如,一个school_records表分区在年柱,各有不同的年值一个单独的数据目录,所有这一年的数据是存储在目录中的数据文件。一个查询,其中包括一个条件,如 WHERE condition such as YEAR=1966, YEAR IN(1989,1999), or YEAR BETWEEN 1984 AND 1989 ,可以检查只有从适当的目录或目录的数据文件,大大减少了数据读取和测试。
以下几个方面介绍分区使用和管理维护:
1)什么时候使用分区表
2)对于分区表的SQL语句
3)静态和动态分区子句
4)分区的子目录的权限
5)查询的分区修剪
6)分区键列
7)设置分区的不同的文件格式
8)管理分区
请参见附加外部分区表的HDFS目录结构为例,说明创建分区表的语法,基础目录结构在HDFS,和如何把分区表数据文件存储的 Impala外其他地方在HDFS。
Parquet 是 Impala表分区的流行格式是因为它很适合处理海量的数据。看到Impala 表分区Parquet 表性能考虑查询性能。
2.1. 什么时候使用分区表
分区通常是适合以下情况:
表是非常大的,在读取整个数据集需要一个不切实际的时间量。
总是或几乎总是在分区列上的条件查询的表。在我们的一个表分区的例子,SELECT COUNT(*) FROM school_records WHERE year= 1985是有效的,只有对数据的一小部分;但SELECT COUNT(*) FROM school_records具有处理每年一个单独的数据文件,从而更全面的工作比在非分区表。如果您经常查询基于姓氏的表,学生证,等等,而不需要测试一年,你可能不会有这样的划分方式。
有合理的基数列(不同值的数量)。如果一个列只有一个小的值,例如男性或女性,你没有得到太多的效率,通过消除只有约50%的数据读取每个查询。如果一列只有几行的匹配值,处理目录的数量可以成为一个限制因素,并在每个目录中的数据文件可能太小,利用Hadoop的机制在多兆字节的数据分块传输。例如,您可能会在一年内分区统计数据,通过年和月的存储销售数据,以及年、月和日的Web流量数据。(一些高容量的输入数据的用户甚至可能划分到每小时和每分钟。)
数据已通过提取、变换、和加载(ETL)管道。分区列的值从原始数据文件中剥离,并由目录名表示,因此将数据加载到分区表中涉及到某种形式的转换或预处理。
2.2. 对于分区表的SQL语句
在Impala的SQL语法,分区影响这些语句:
Create table :您在创建表时指定了一个PARTITIONED BY条件,以确定分区列的名称和数据类型。这些列不包含在表的列中的主要列表中。
在CDH 5.7 /Impala2.5及更高,你也可以使用分区在创建表的条款为SELECT语句。此语法允许您使用一个语句来创建一个分区表,将数据复制到它,并基于插入的数据中的值创建新的分区。
改变表:可以添加或删除分区,可以使用一个庞大的数据集的不同部分工作。你可以为一个特定的分区指定的HDFS目录保存数据文件。通过日期值划分的数据,您可能会“老化”不再相关的数据。
注:如果您正在创建一个分区,并指定它的位置,为最大效率,使用一个单一的更改表语句,包括添加分区和位置子句,而不是单独的语句与添加分区和设置位置子句。
2.3. 静态和动态分区子句
在SQL语句中指定的所有分区列称为静态分配,因为语句影响单个预测分区。例如,您使用静态分区与一个改变表语句,只影响一个分区,或与一个插入语句插入到同一个分区中的所有值:
Insert into t1 partition(x=10,y='a') select c1 from some_other_table;
当你指定分区键列在INSERT语句,但离开了价值,Impala决定插入哪个分区。这种技术被称为动态分区:
insert into t1 partition(x,y='b') select c1, c2 from some_other_table;
-- Create new partition if necessary based on variable year, month, and day; insert asingle value.
insert into weather partition(year, month, day) select 'cloudy',2014,4,21;
-- Create new partition if necessary for specified year and month but variable day;insert a single value.
insert into weather partition(year=2014, month=04, day) select'sunny',22;
在分区子句中指定的更重要的列,在“选择列表”中需要的列数较少。在选择列表中的尾随列以顺序替换没有指定值的分区键列。
2.4. 分区的子目录的权限
默认情况下,如果插入语句创建任何新的子目录下面的分区表,这些子目录分配权限的用户默认的HDFS的权限。使每个子目录具有相同的权限为在HDFS的父目录,指定--insert_inherit_permissions启动选项的impalad守护。
2.5. 查询的分区精简
分区精简指的是一个查询可以跳过一个或多个分区对应的数据文件的机制。如果您可以安排查询,从查询执行计划中删除大量的不必要的分区,查询使用更少的资源,因此比例更快,更可扩展性。
例如,如果一个表是由列年,月,日,分区,然后在条款如年为2013年,其中<2010,或1995和1998让Impala跳过数据文件在指定范围外的所有分区之间。同样地,在一年的2013和1和3之间的一个月,可以精简更多的分区,读取数据文件只有一年的一部分。
要检查分区修剪对于查询的有效性,在运行它之前检查解释输出为查询的结果。例如,这个示例显示了一个有3个分区的表,其中查询只读取其中的1个分区。符号#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;
+------------------------------------------------------------------+
| ExplainString |
+------------------------------------------------------------------+
| PLANFRAGMENT 0|
| PARTITION: UNPARTITIONED |
| |
| 1:EXCHANGE |
| |
| PLANFRAGMENT 1 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 1 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=predicate_propagation.census #partitions=1/3 size=12B |
+------------------------------------------------------------------+
对于在查询的每个阶段实际读取和处理的数据量的报表,在运行查询后立即检查汇总命令的输出。对于一个更详细的分析,看配置文件命令的输出;它包括在配置文件输出的开始附近的这个相同的汇总报告。
1)检查是否对查询进行分区修剪
2)什么SQL构造分区修剪工作
3)动态分区修剪
2.5.1. 检查是否对查询进行分区修剪
要检查分区修剪对于查询的有效性,在运行它之前检查解释输出为查询的结果。例如,这个示例显示了一个有3个分区的表,其中查询只读取其中的1个分区。符号#分区= 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;
+------------------------------------------------------------------+
| ExplainString |
+------------------------------------------------------------------+
| PLANFRAGMENT 0|
| PARTITION: UNPARTITIONED |
| |
| 1:EXCHANGE |
| |
| PLANFRAGMENT 1|
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 1 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=predicate_propagation.census #partitions=1/3 size=12B |
+------------------------------------------------------------------+
对于在查询的每个阶段实际读取和处理的数据量的报表,在运行查询后立即检查汇总命令的输出。对于一个更详细的分析,看配置文件命令的输出;它包括在配置文件输出的开始附近的这个相同的汇总报告。
2.5.2. 什么SQL构造分区修剪工作
impala甚至可以做分区修剪的情况下,分区键列是不能直接比较恒定,通过传递性质的WHERE子句中的其他部分。这种技术被称为谓词的传播,并在impala1.2.2后来。在这个示例中,普查表包括另一列,该列指示当数据被收集时,发生在10年的时间间隔内。即使查询并不比分区键列(年)到一个恒定值,impala可以推断出,只有= 2010是必需的分区的一年,又一次只读取了3个分区1。
[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 andcensus_year=2010;
+------------------------------------------------------------------+
| ExplainString |
+------------------------------------------------------------------+
| PLANFRAGMENT 0|
| PARTITION: UNPARTITIONED |
| |
| 1:EXCHANGE |
| |
| PLANFRAGMENT 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 |
+------------------------------------------------------------------+
如果一个视图适用于一个分区表,任何分区修剪都认为在原始查询和任何额外的谓词在查询中的语句,是指视图的子句。impala1.4之前,只有在条款对原始查询从创建视图的语句进行分区修剪。
在解析函数和分区表的查询中,只发生在由解析函数调用的分区中命名的列的分区修剪。例如,如果一个解析函数查询有一个条款,如在年= 2016,使查询修剪所有其他年分区的方法是包括在解析函数调用划分;例如,在(分区的一年,other_columns other_analytic_clauses)。
2.5.3. 动态分区修剪
原来的机制用于修剪分区是静态分区修剪,在其中的条件,在条款进行分析,以确定提前哪些分区可以安全地跳过。在Impala 2.5 /CDH5.7及更高版本,impala可以执行动态分区修剪,在分区信息中查询收集,和impala修剪不必要的分区方式是提前预测不切实际。
例如,如果分区键列进行比较的文字值WHERE子句中,impala可以执行静态分区修剪规划阶段在阅读相关的分区:
-- The query only needs to read 3 partitions whose key values are known ahead of time.
-- That's static partition pruning.
SELECTCOUNT(*) FROM sales_table WHERE year IN (2005, 2010, 2015);
动态分区修剪涉及使用信息只有在运行时,如查询结果:
Create table yy (s string) partitioned by (year int) stored as parquet;
insert into yy partition (year) values ('1999', 1999), ('2000', 2000),
('2001', 2001), ('2010',2010);
computestats yy;
create table yy2 (s string) partitioned by (year int) stored as parquet;
insert intoyy2 partition (year) values ('1999', 1999), ('2000', 2000),
('2001', 2001);
computestats yy2;
-- The query reads an unknown number of partitions, whose key values are only
-- known at run time. The 'runtime filters' lines show how the information about
-- the partitions is calculated in query fragment 02, and then used in query
-- fragment00 to decide which partitions to skip.
Explain select s from yy2 where year in (select year from yy where year between 2000and 2005);
+----------------------------------------------------------+
| ExplainString|
+----------------------------------------------------------+
| EstimatedPer-Host Requirements: Memory=16.00MB VCores=2 |
| |
|04:EXCHANGE [UNPARTITIONED] |
| | |
| 02:HASHJOIN [LEFT SEMI JOIN, BROADCAST] |
| | hash predicates: year = year |
| | runtime filters: RF000 <- year |
| | |
||--03:EXCHANGE [BROADCAST] |
| | | |
| | 01:SCAN HDFS [dpp.yy] |
| | partitions=2/4 files=2 size=468B |
| | |
| 00:SCANHDFS [dpp.yy2] |
| partitions=2/3 files=2 size=468B |
| runtime filters: RF000 -> year |
+----------------------------------------------------------+
在这种情况下,impala评价子查询,子查询结果发送所有Impala节点参与查询,然后每个impalad守护进程采用动态分区剪枝优化与相关键值只读分区。
动态分区修剪是特别有效的查询,涉及几个大的分区表的联接。评估联接谓词的子句,通常需要从某些表的所有分区中读取数据。如果该查询的WHERE子句中引用的分区键列,impala现在经常可以跳过阅读许多的分区在评估条款。动态分区修剪优化减少了在查询过程中的网络存储和传输的I / O和中间数据量的量。
当溢出到磁盘功能是一个连接节点在查询激活,impala不产生任何运行过滤器,主机上的连接操作。查询中的其他连接节点不受影响。
动态分区修剪是运行时过滤功能的一部分,它适用于其他类型的查询,除了对分区表的查询。看到运行的impala查询有关此功能的详细的过滤。
2.6. 分区键列
您选择的列作为分区键应该是经常用于筛选查询结果的重要的大型查询。流行的例子是一些组合的一年,一个月,和一天的数据有相关的时间值,和地理区域的数据时,与一些地方。
基于时间的数据,分离出独立的部分纳入自己的栏目,因为impala不能划分一个时间戳列。
该分区列的数据类型不具有对存储要求的效果显著,因为从这些列的值不存储在数据文件中,而他们是在HDFS目录名称的字符串。
在CDH 5.7 /impala2.5及更高版本,可以使optimize_partition_key_scans查询选项来加快查询的速度,仅指分区键列,如选择最大(年)。默认情况下,此设置没有启用,因为如果表中包含没有实际数据的分区目录,则查询的行为将略有不同。看到optimize_partition_key_scans查询详情。
分区表可以包含复杂的类型列。所有分区键列必须为标量类型。
记住,当impala查询存储在HDFS的数据,它是最有效的使用多字节的文件利用HDFS块大小。实木复合地板表,块的大小(和数据文件大小是理想) 256 MB,后来impala。因此,避免指定太多的分区键列,这可能会导致单个分区只包含少量的数据。例如,如果你每天收到1个数据,你可能会被一年一个月,一天一天;而如果你每分钟收到5个数据,你可能会被一年、一个月、一天、一小时、一分钟划分。如果你与一个地理成分的数据,你可能会划分邮政编码,如果您有许多兆字节的每个邮政编码数据,但如果没有的话,你可能会被一些大的区域,如城市、州或国家划分。状态
如果你经常运行汇总等功能min(),max(),计数(不同的)分区键列,考虑启用optimize_partition_key_scans查询优化查询。这一特征在CDH 5.7 /impala2.5及更高版本可用。看到optimize_partition_key_scans查询选项,这个选项适用于查询的种类,和轻微的差异如何分区进行评估时,该查询选项启用。
2.7. 设置分区的不同的文件格式
分区表有灵活性,使用不同的分区使用不同的文件格式。(关于不同的文件格式支持背景信息看,impala、impala和Hadoop文件格式。)例如,如果你在文本格式最初收到数据,然后接收新的数据格式,并最终开始RCFile,拼花格式接收数据,这些数据可以驻留在同一个表的查询。您只需要确保表的结构,以便使用不同的文件格式的数据文件驻留在单独的分区中。
例如,这里是你如何可以从文本到地板的数据你不同年接收数据:
[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包含一个复合数据文件。和总是一样,当加载不平凡的数据时,您将使用插入…选择或加载数据以大批量导入数据,而不是插入…值,产生小的文件,是低效的现实世界的查询。
对于其他类型的文件,impala不能创造本身,你可以切换到Hive的问题修改表…设置文件格式报表和报表数据插入或负载有。切换回Impala后,发出声明,刷新table_name Impala承认任何分区或新添加的数据通过hive。
2.8. 管理分区
你可以添加,删除,设定预期的文件格式,或一组数据文件HDFS位置个别分区impala表内。有关语法细节的更改表语句,并在包含分区的分区的管理表上设置不同的文件格式的不同的文件格式。
注:如果您正在创建一个分区,并指定它的位置,为最大效率,使用一个单一的更改表语句,包括添加分区和位置子句,而不是单独的语句与添加分区和设置位置子句。
当一个分区被删除时,数据文件会发生什么,取决于分区表是否被指定为内部或外部的。对于内部(托管)表,数据文件已被删除。例如,如果分区表中的数据是存储在其他地方的原始数据文件的副本,则可以通过删除不再需要的旧分区来保存磁盘空间,知道原始数据在需要时仍然可用。对于一个外部表,数据文件将被单独留下。例如,删除一个分区没有删除相关的文件让impala考虑更小的分区,提高查询效率和减少表的DDL操作的开销;如果数据再次需要后,你可以再添加分区。看到的细节和例子的impala表概述。
3. impala连接查询的性能优化
涉及连接操作的查询通常需要更多的调整,而不是仅指一个表的查询。从联接查询集合查询的结果集的最大大小是所有联接表中的行数的乘积。当加入数个表有数以百万计或数十亿的行,任何错过的机会过滤结果集,或其他低效的查询,可能导致一个操作,不完成在一个实际的时间,必须被取消。
调整Impala的最简单的方法连接查询是收集统计每个表参与联接的计算统计表,然后让Impala自动优化基于每个表的大小的查询,对每一列的不同值的数量,等等。计算统计表和连接优化了Impala1.2.2新特点。对于每个表的精确统计,在将数据加载到该表中后,发出计算统计报表,如果数据量大幅度的改变,加载数据,添加一个分区,等等。
如果没有可用的统计信息在连接查询所有表,或者如果Impala选择连接顺序,是不是最有效的,你可以重写自动连接顺序优化通过指定straight_join关键词后立即选择关键词。在这种情况下,Impala用出现的查询指导顺序处理。
当你使用straight_join技术,你必须手动而不是依靠Impala优化器查询表的连接。该优化使用复杂的技术来估计连接的每个阶段的结果集的大小。对于手动排序,采用这种启发式的方法开始,然后实验来微调顺序:
指定最大的表。这个表是由每个Impala节点从磁盘读取,其规模不是很大的内存使用情况的查询。
下一步,指定最小的表。第二、第三、等表的内容都在网络上传输。要将连接查询的每个后续阶段的结果集的大小减到最小。最有可能的方法是先加入一个小的表,这样结果集仍然很小,即使随后的较大的表被处理。
加入下一个最小的表,然后是下一个最小的,等等。
例如,如果你有表大,中,小,微小,逻辑连接顺序尝试将是大,微小,小,中。
术语“最大”和“最小”是指基于每个表中的行和列的数量的中间结果集的大小,是结果集的一部分。例如,如果你加入一个表的销售与另一个表的客户,查询可能会发现从100个不同的客户,共有5000采购的结果。在这种情况下,您将指定选择…从销售连接客户……,把客户放在右边,因为它在这个查询的上下文中是小的。
impala的查询计划选择不同的技术之间进行连接查询,根据表的绝对和相对大小。广播连接是默认的,在右边的表被认为是小于左边的表,它的内容被发送到查询中涉及的所有其他节点上。另一种技术被称为一个分区的连接(不涉及到一个分区表),这是更适合于大表的大小大致相等。使用这种技术,每个表的一部分被发送到适当的其他节点,其中的行的子集可以被并行处理。广播或分区连接的选择也取决于在联接中的所有表可用的统计数据,由计算统计报表所收集的数据中的所有表。
要查看哪些连接策略用于某个特定的查询,为查询发出一个解释语句。如果你发现一个查询使用广播连接,当你知道通过基准,一个分区的连接将是更有效的,或反之亦然,向查询添加一个提示,以指定使用精确的连接机制。在Impala的SELECT语句详见查询提示。
3.1. 当统计数字不可用时如何处理
如果表或列统计信息不可用,在加入一些表,impala还是重新排序表使用信息是可用的。表统计放在连接顺序的左侧,在成本递减的顺序,基于整体规模和基数。没有统计的表被视为零大小,也就是说,它们总是放在连接顺序的右边。
3.2. straight_join连接顺序大于其他
如果Impala连接查询是没有效率的,过时的统计数据或意外的数据分布,你可以把impala从排序连接表采用straight_join关键词后立即选择关键词。的straight_join关键词关闭重新加入条款,impala是内部,并产生一个依赖于加入条款被有序的优化查询文本中的计划。在这种情况下,重写查询,以便最大的表在左边,其次是下一个最大的,等等,直到最小的表在右边。
在这个例子中,从大表的子查询产生一个非常小的结果集,但表可能仍然被视为最大的连接顺序放在第一。使用straight_join最后加入条款阻止最终的表被重新排序,使其在最右边的表的连接顺序。
selectstraight_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;
3.3. 连接顺序优化实例
这里的实际例子从侧面证明:调整Impala的最简单的方法连接查询是收集统计每个表参与联接的计算统计表。
这里有示例显示在表之间有10亿、2亿和100万行的连接。(在这种情况下,表没有分区和使用Parquet格式。)小表包含从最大的一个数据子集,对加入的唯一ID列方便。最小的表只包含从其他表中的列的子集。
[localhost:21000]> create table big stored as parquet as select * from raw_data;
+----------------------------+
|summary |
+----------------------------+
| Inserted1000000000 row(s) |
+----------------------------+
|||Returned1 row(s) in 671.56s
[localhost:21000]> desc big;
+-----------+---------+---------+
| name | type | comment |
+-----------+---------+---------+
| id | int | |
| val| int | |
|zfill | string | |
| name | string | |
| assertion| boolean | |
+-----------+---------+---------+
Returned 5row(s) in 0.01s
[localhost:21000] > create table mediumstored as parquet as select * from big limit 200 * floor(1e6);
+---------------------------+
|summary |
+---------------------------+
| Inserted200000000 row(s) |
+---------------------------+
|Returned 1row(s) in 138.31s
[localhost:21000]> create table small stored as parquet as select id,val,name from big whereassertion = true limit 1 * floor(1e6);
+-------------------------+
|summary |
+-------------------------+
| Inserted1000000 row(s) |
+-------------------------+
|Returned 1row(s) in 6.32s
对于任何一种性能试验,使用EXPLAIN语句看到任何昂贵的查询将不进行实际运行,使冗长的解释计划包含更注重性能的细节:最有趣的计划线路以粗体突出显示,显示没有连接表统计,impala不能在处理各阶段涉及的行数的一个很好的估计,并可能坚持广播加入机制,将一张表完全复制到每个节点。
[localhost:21000]> set explain_level=verbose;
EXPLAIN_LEVELset to verbose
[localhost:21000]> explain select count(*) from big join medium where big.id = medium.id;
+----------------------------------------------------------+
| ExplainString|
+----------------------------------------------------------+
| EstimatedPer-Host Requirements: Memory=2.10GB VCores=2 |
| |
| PLANFRAGMENT 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 |
| |
| PLANFRAGMENT 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 |
| | joinop: 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 |
| |
| PLANFRAGMENT 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 64row(s) in 0.04s
收集所有表的统计数据是简单的,一个计算每表的计算统计语句:
[localhost:21000]> compute stats small;
+-----------------------------------------+
|summary |
+-----------------------------------------+
| Updated 1partition(s) and 3 column(s). |
+-----------------------------------------+
|Returned 1row(s) in 4.26s
[localhost:21000]> compute stats medium;
+-----------------------------------------+
|summary |
+-----------------------------------------+
| Updated 1partition(s) and 5 column(s). |
+-----------------------------------------+
|Returned 1row(s) in 42.11s
[localhost:21000]> compute stats big;
+-----------------------------------------+
|summary |
+-----------------------------------------+
| Updated 1partition(s) and 5 column(s). |
+-----------------------------------------+
|Returned 1row(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
+-----------------------------------------------------------+
| ExplainString |
+-----------------------------------------------------------+
| EstimatedPer-Host Requirements: Memory=937.23MB VCores=2 |
| |
| PLANFRAGMENT 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 |
| |
| PLANFRAGMENT 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/1size=23.12GB |
| table stats: 1000000000 rows total |
| column stats: all |
| cardinality: 1000000000 |
| per-host memory: 88.00MB |
| tuple ids: 1 |
| |
| PLANFRAGMENT 2 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 4 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=join_order.medium #partitions=1/1size=4.62GB |
| table stats: 200000000 rows total |
| column stats: all |
| cardinality: 200000000 |
| per-host memory: 88.00MB |
| tuple ids: 0 |
+-----------------------------------------------------------+
Returned 64row(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
+-----------------------------------------------------------+
| ExplainString |
+-----------------------------------------------------------+
| EstimatedPer-Host Requirements: Memory=101.15MB VCores=2 |
| |
| PLANFRAGMENT 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 |
| |
| PLANFRAGMENT 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/1size=23.12GB |
| table stats: 1000000000 rows total |
| column stats: all |
| cardinality: 1000000000 |
| per-host memory: 88.00MB |
| tuple ids: 1 |
| |
| PLANFRAGMENT 2 |
| PARTITION: RANDOM |
| |
| STREAM DATA SINK |
| EXCHANGE ID: 4 |
| UNPARTITIONED |
| |
| 0:SCAN HDFS |
| table=join_order.small #partitions=1/1size=17.93MB |
| table stats: 1000000 rows total |
| column stats: all |
| cardinality: 1000000 |
| per-host memory: 32.00MB |
| tuple ids: 0 |
+-----------------------------------------------------------+
Returned 64row(s) in 0.03s
当这些查询实际上是运行时,无论查询文本中的表顺序,执行时间都是相对一致的。这里是一个例子使用独特的ID列包含重复值的列的值:
[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 1row(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 1row(s) in 20.45s
[localhost:21000]> select count(*) from big join small on (big.val = small.val);
+------------+
|count(*) |
+------------+
|2000948962 |
+------------+
|Returned 1row(s) in 108.85s
[localhost:21000]> select count(*) from small join big on (big.val = small.val);
+------------+
|count(*) |
+------------+
|2000948962 |
+------------+
|Returned 1row(s) in 100.76s
注意:当检查联接查询的性能和联接顺序优化的有效性时,请确保查询包含足够的数据和群集资源,以查看基于查询计划的差异。例如,一个只有几兆的单个数据文件驻留在一个单一的HDFS块,在一个单一的节点处理。同样,如果使用单个节点或两个节点群集,广播或分区的联接策略的效率可能不会有太大的差异。
4. impala表和列信息统计操作
4.1. 表和列的信息统计
show table stats parquet_snappy;
compute stats parquet_snappy;
n 如果是hive的话,统计信息命令如下
u ANALYZE TABLE COMPUTE STATISTICS FOR COLUMNS
show table stats parquet_snappy;
+-------+--------+---------+--------------+-------------------+---------+-------------------+...
| #Rows | #Files | Size | Bytes Cached | Cache Replication | Format | Incremental stats |...
+-------+--------+---------+--------------+-------------------+---------+-------------------+...
| -1 | 96 | 23.35GB | NOT CACHED | NOT CACHED | PARQUET | false |...
+-------+--------+---------+--------------+-------------------+---------+-------------------+...
compute stats parquet_snappy;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 6 column(s). |
+-----------------------------------------+
show table stats parquet_snappy;
+------------+--------+---------+--------------+-------------------+---------+-------------------+...
| #Rows | #Files | Size | Bytes Cached | Cache Replication | Format | Incremental stats |...
+------------+--------+---------+--------------+-------------------+---------+-------------------+...
| 1000000000 | 96 | 23.35GB | NOT CACHED | NOT CACHED | PARQUET | false |...
+------------+--------+---------+--------------+-------------------+---------+-------------------+...
4.2. 关于列的信息统计
show column stats parquet_snappy;
compute stats parquet_snappy;
show column stats parquet_snappy;
+-------------+----------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+-------------+----------+------------------+--------+----------+----------+
| id | BIGINT | -1 | -1 | 8 | 8 |
| val | INT | -1 | -1 | 4 | 4 |
| zerofill | STRING | -1 | -1 | -1| -1|
| name | STRING | -1 | -1 | -1| -1|
| assertion | BOOLEAN | -1 | -1 | 1 | 1 |
| location_id | SMALLINT | -1 | -1 | 2 | 2 |
+-------------+----------+------------------+--------+----------+----------+
compute stats parquet_snappy;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 6 column(s). |
+-----------------------------------------+
show column stats parquet_snappy;
+-------------+----------+------------------+--------+----------+-------------------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+-------------+----------+------------------+--------+----------+-------------------+
| id | BIGINT | 183861280 | -1 | 8 | 8 |
| val | INT | 139017 | -1 | 4 | 4 |
| zerofill | STRING | 101761 | -1 | 6 | 6 |
| name | STRING | 145636240 | -1 | 22| 13.00020027160645 |
| assertion | BOOLEAN | 2 | -1 | 1 | 1 |
| location_id | SMALLINT | 339| -1 | 2 | 2 |
+-------------+----------+------------------+--------+----------+-------------------+
4.3. 有关分区表的信息统计
show partitions year_month_day;
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
| year | month | day | #Rows | #Files | Size | Bytes Cached | Cache Replication | Format |...
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
| 2013 | 12 | 1 | -1 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 2 | -1 | 1 | 2.53MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 3 | -1 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 4 | -1 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 5 | -1 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| Total || | -1 | 5 | 12.58MB | 0B | | |...
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
show table stats year_month_day;
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
| year | month | day | #Rows | #Files | Size | Bytes Cached | Cache Replication | Format |...
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
| 2013 | 12 | 1 | -1 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 2 | -1 | 1 | 2.53MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 3 | -1 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 4 | -1 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 5 | -1 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| Total || | -1 | 5 | 12.58MB | 0B | | |...
+-------+-------+-----+-------+--------+---------+--------------+-------------------+---------+...
show column stats year_month_day;
+-----------+---------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+-----------+---------+------------------+--------+----------+----------+
| id | INT | -1 | -1 | 4 | 4 |
| val| INT | -1 | -1 | 4 | 4 |
| zfill | STRING | -1 | -1 | -1| -1|
| name | STRING | -1 | -1 | -1| -1|
| assertion | BOOLEAN | -1 | -1 | 1 | 1 |
| year | INT | 1 | 0 | 4 | 4 |
| month | INT | 1 | 0 | 4 | 4 |
| day| INT | 5 | 0 | 4 | 4 |
+-----------+---------+------------------+--------+----------+----------+
compute stats year_month_day;
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 5 partition(s) and 5 column(s). |
+-----------------------------------------+
show table stats year_month_day;
+-------+-------+-----+--------+--------+---------+--------------+-------------------+---------+...
| year | month | day | #Rows | #Files | Size | Bytes Cached | Cache Replication | Format |...
+-------+-------+-----+--------+--------+---------+--------------+-------------------+---------+...
| 2013 | 12 | 1 | 93606 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 2 | 94158 | 1 | 2.53MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 3 | 94122 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 4 | 93559 | 1 | 2.51MB | NOT CACHED | NOT CACHED | PARQUET |...
| 2013 | 12 | 5 | 93845 | 1 | 2.52MB | NOT CACHED | NOT CACHED | PARQUET |...
| Total || | 469290 | 5 | 12.58MB | 0B | | |...
+-------+-------+-----+--------+--------+---------+--------------+-------------------+---------+...
show column stats year_month_day;
+-----------+---------+------------------+--------+----------+-------------------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+-----------+---------+------------------+--------+----------+-------------------+
| id | INT | 511129 | -1 | 4 | 4 |
| val| INT | 364853 | -1 | 4 | 4 |
| zfill | STRING | 311430 | -1 | 6 | 6 |
| name | STRING | 471975 | -1 | 22| 13.00160026550293 |
| assertion | BOOLEAN | 2 | -1 | 1 | 1 |
| year | INT | 1 | 0 | 4 | 4 |
| month | INT | 1 | 0 | 4 | 4 |
| day| INT | 5 | 0 | 4 | 4 |
+-----------+---------+------------------+--------+----------+-------------------+
4.4. 增量信息统计
在2.1.0高,你可以使用语法计算增量数据和增量数据下降。增量子句与增量统计工作,是一个专门的功能分区表,是大或经常更新新的分区。
INCREMENTAL STATS or DROP INCREMENTAL STATS statement.
4.5. 什么时候需要重新统计信息
当一个内容表或分区明显变化,重新计算统计相关数据表或分区。
变化是“重大”的程度不同,根据表的绝对和相对大小。
通常,如果你添加了30%多个数据表,这是值得重新计算统计,因为行和不同值的数量差异可能导致impala选择不同的连接顺序时,表中使用的查询。这个指南对于最大的表是最重要的。
例如,增加30%个新的数据表中含有1 TB的具有更大的影响比加入顺序加30%表只包含几兆字节,而较大的表对查询性能有较大的影响如果impala选择一个次优顺序连接由于过时的统计数据。
如果你加载一个完整的数据表中的数据的新的集合,而每一列的行数和不同值的数量是相对不变的,你不需要重新计算统计表。
如果一个表的数据是过时的,和表的大小使它重新计算新的数据立即不切实际,你可以使用下拉数据声明删除过时的数据,使其更容易识别,需要一个新的计算统计操作表。
对于一个大的分区表,请考虑使用增量统计特征在Impala 2.1.0高可用,在增量统计概要说明。如果你添加一个新的分区表,这是值得重新计算增量数据,因为操作只需扫描数据,一个新的分区。
4.6. 查看表和列的统计信息样例
[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_percentage | FLOAT | -1 | -1 | 4 | 4 |
+--------------------+-----------+------------------+--------+----------+----------+
Returned 29 row(s) in 0.04s
在分析列统计表的表报表时,您必须指定用于收集统计数据的每个列。impala计算统计报表自动汇总所有列的统计,因为它读取整个表比较快,可以有效地计算所有列的值。这个例子显示了运行后的计算统计报表,统计数据被填充在表和它的所有列中:
[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 | -1 | 4 | 4 |
| s_store_id | STRING | 6 | -1 | 16| 16 |
| s_rec_start_date | TIMESTAMP | 4 | -1 | 16| 16 |
| s_rec_end_date | TIMESTAMP | 3 | -1 | 16| 16 |
| s_closed_date_sk | INT| 3 | -1 | 4 | 4 |
| s_store_name| STRING | 8 | -1 | 5 | 4.25|
| s_number_employees | INT| 9 | -1 | 4 | 4 |
| s_floor_space | INT| 10 | -1 | 4 | 4 |
| s_hours | STRING | 2 | -1 | 8 | 7.083300113677979 |
| s_manager | STRING | 7 | -1 | 15| 12 |
| s_market_id | INT| 7 | -1 | 4 | 4 |
| s_geography_class | STRING | 1 | -1 | 7 | 7 |
| s_market_desc | STRING | 10 | -1 | 94| 55.5|
| s_market_manager | STRING | 7 | -1 | 16| 14 |
| s_division_id | INT| 1 | -1 | 4 | 4 |
| s_division_name | STRING | 1 | -1 | 7 | 7 |
| s_company_id| INT| 1 | -1 | 4 | 4 |
| s_company_name | STRING | 1 | -1 | 7 | 7 |
| s_street_number | STRING | 9 | -1 | 3 | 2.833300113677979 |
| s_street_name | STRING | 12 | -1 | 11| 6.583300113677979 |
| s_street_type | STRING | 8 | -1 | 9 | 4.833300113677979 |
| s_suite_number | STRING | 11 | -1 | 9 | 8.25|
| s_city | STRING | 2 | -1 | 8 | 6.5 |
| s_county | STRING | 1 | -1 | 17| 17 |
| s_state | STRING | 1 | -1 | 2 | 2 |
| s_zip| STRING | 2 | -1 | 5 | 5 |
| s_country | STRING | 1 | -1 | 13| 13 |
| s_gmt_offset| FLOAT | 1 | -1 | 4 | 4 |
| s_tax_percentage | FLOAT | 5 | -1 | 4 | 4 |
+--------------------+-----------+------------------+--------+----------+-------------------+
Returned 29 row(s) in 0.04s
下面的示例显示了如何将统计数据表示为一个分区表。在这种情况下,我们已经建立了一个表,以保持世界上最琐碎的人口普查数据,一个单一的字符串字段,按一年的列分区。表统计包括每个分区的单独的条目,以及数字字段的最终总计。列数据包括分区列一些容易推断出来的事实,如不同值的数量(划分子目录的数量)。
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 | -1 | 2 | 2 |
+--------+----------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.02s
The following example shows how the statistics are filled in by a COMPUTE STATS statement in Impala.
[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 | -1 | 2 | 2 |
+--------+----------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.02s