本帖最后由 丫丫 于 2016-12-5 16:42 编辑
问题导航
1、什么时候使用分区表?
2、在Impala的SQL语法,分区影响哪些语句?
3、静态和动态分区子句什么区别?
4、分区的子目录是什么权限?
5、什么是分区精简?
6、如何检查分区修剪对于查询的有效性?
7、检查是否需要对查询进行分区修剪?
8、什么SQL构造分区修剪工作?
9、如何动态分区修剪?
10、如何选择分区键列
11、分区有哪些不同文件格式?
12、如何管理分区?
1.1 Hadoop-Impala十大优化系列之(1)—分区表优化-8个方法让分区最优化impala表分区
默认情况下,表中的所有数据文件都位于一个目录中。分区是在加载过程中基于从一个或多个列的值的物理上划分数据的技术,以加快对这些列进行测试的查询。例如,一个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 表性能考虑查询性能。
1.1.1 什么时候使用分区表
分区通常是适合以下情况:
表是非常大的,在读取整个数据集需要一个不切实际的时间量。
总是或几乎总是在分区列上的条件查询的表。在我们的一个表分区的例子,SELECT COUNT(*) FROM school_records WHERE year= 1985是有效的,只有对数据的一小部分;但SELECT COUNT(*) FROM school_records具有处理每年一个单独的数据文件,从而更全面的工作比在非分区表。如果您经常查询基于姓氏的表,学生证,等等,而不需要测试一年,你可能不会有这样的划分方式。
有合理的基数列(不同值的数量)。如果一个列只有一个小的值,例如男性或女性,你没有得到太多的效率,通过消除只有约50%的数据读取每个查询。如果一列只有几行的匹配值,处理目录的数量可以成为一个限制因素,并在每个目录中的数据文件可能太小,利用Hadoop的机制在多兆字节的数据分块传输。例如,您可能会在一年内分区统计数据,通过年和月的存储销售数据,以及年、月和日的Web流量数据。(一些高容量的输入数据的用户甚至可能划分到每小时和每分钟。)
数据已通过提取、变换、和加载(ETL)管道。分区列的值从原始数据文件中剥离,并由目录名表示,因此将数据加载到分区表中涉及到某种形式的转换或预处理。
1.1.2 对于分区表的SQL语句
在Impala的SQL语法,分区影响这些语句:
createtable :您在创建表时指定了一个PARTITIONEDBY条件,以确定分区列的名称和数据类型。这些列不包含在表的列中的主要列表中。
在CDH 5.7 /Impala2.5及更高,你也可以使用分区在创建表的条款为SELECT语句。此语法允许您使用一个语句来创建一个分区表,将数据复制到它,并基于插入的数据中的值创建新的分区。
改变表:可以添加或删除分区,可以使用一个庞大的数据集的不同部分工作。你可以为一个特定的分区指定的HDFS目录保存数据文件。通过日期值划分的数据,您可能会“老化”不再相关的数据。
注:如果您正在创建一个分区,并指定它的位置,为最大效率,使用一个单一的更改表语句,包括添加分区和位置子句,而不是单独的语句与添加分区和设置位置子句。
1.1.3 静态和动态分区子句
在SQL语句中指定的所有分区列称为静态分配,因为语句影响单个预测分区。例如,您使用静态分区与一个改变表语句,只影响一个分区,或与一个插入语句插入到同一个分区中的所有值:
insertinto t1 partition(x=10,y='a') select c1 from some_other_table;
当你指定分区键列在INSERT语句,但离开了价值,Impala决定插入哪个分区。这种技术被称为动态分区:
[mw_shl_code=text,true]insert intot1 partition(x,y='b') select c1, c2 from some_other_table;
-- Createnew partition if necessary based on variable year, month, and day; insert asingle value.
insert intoweather partition(year, month, day) select'cloudy',2014,4,21;
-- Createnew partition if necessary for specified year and month but variable day;insert a single value.
insert intoweather partition(year=2014, month=04, day) select'sunny',22;[/mw_shl_code]
在分区子句中指定的更重要的列,在“选择列表”中需要的列数较少。在选择列表中的尾随列以顺序替换没有指定值的分区键列。
1.1.4 分区的子目录的权限
默认情况下,如果插入语句创建任何新的子目录下面的分区表,这些子目录分配权限的用户默认的HDFS的权限。使每个子目录具有相同的权限为在HDFS的父目录,指定--insert_inherit_permissions启动选项的impalad守护。
1.1.5 查询的分区精简
分区精简指的是一个查询可以跳过一个或多个分区对应的数据文件的机制。如果您可以安排查询,从查询执行计划中删除大量的不必要的分区,查询使用更少的资源,因此比例更快,更可扩展性。
例如,如果一个表是由列年,月,日,分区,然后在条款如年为2013年,其中<2010,或1995和1998让Impala跳过数据文件在指定范围外的所有分区之间。同样地,在一年的2013和1和3之间的一个月,可以精简更多的分区,读取数据文件只有一年的一部分。
要检查分区修剪对于查询的有效性,在运行它之前检查解释输出为查询的结果。例如,这个示例显示了一个有3个分区的表,其中查询只读取其中的1个分区。符号#partitions=1/3在解释计划证实了impala可以做适当的分区修剪。
[mw_shl_code=text,true][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 censuswhere 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 |
+------------------------------------------------------------------+[/mw_shl_code]
对于在查询的每个阶段实际读取和处理的数据量的报表,在运行查询后立即检查汇总命令的输出。对于一个更详细的分析,看配置文件命令的输出;它包括在配置文件输出的开始附近的这个相同的汇总报告。
1) 检查是否对查询进行分区修剪
2) 什么SQL构造分区修剪工作
3) 动态分区修剪
1.1.5.1 检查是否对查询进行分区修剪
要检查分区修剪对于查询的有效性,在运行它之前检查解释输出为查询的结果。例如,这个示例显示了一个有3个分区的表,其中查询只读取其中的1个分区。符号#分区= 1 / 3在解释计划证实了impala可以做适当的分区修剪。
[mw_shl_code=text,true]
[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 censuswhere 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 |
+------------------------------------------------------------------+[/mw_shl_code]
对于在查询的每个阶段实际读取和处理的数据量的报表,在运行查询后立即检查汇总命令的输出。对于一个更详细的分析,看配置文件命令的输出;它包括在配置文件输出的开始附近的这个相同的汇总报告。
1.1.5.2 什么SQL构造分区修剪工作
impala甚至可以做分区修剪的情况下,分区键列是不能直接比较恒定,通过传递性质的WHERE子句中的其他部分。这种技术被称为谓词的传播,并在impala1.2.2后来。在这个示例中,普查表包括另一列,该列指示当数据被收集时,发生在10年的时间间隔内。即使查询并不比分区键列(年)到一个恒定值,impala可以推断出,只有= 2010是必需的分区的一年,又一次只读取了3个分区1。
[mw_shl_code=text,true]
[localhost:21000]> drop table census;
[localhost:21000]> create table census (name string, census_year int) partitioned by (yearint);
[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 censuswhere 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 |
+------------------------------------------------------------------+[/mw_shl_code]
如果一个视图适用于一个分区表,任何分区修剪都认为在原始查询和任何额外的谓词在查询中的语句,是指视图的子句。impala1.4之前,只有在条款对原始查询从创建视图的语句进行分区修剪。
在解析函数和分区表的查询中,只发生在由解析函数调用的分区中命名的列的分区修剪。例如,如果一个解析函数查询有一个条款,如在年= 2016,使查询修剪所有其他年分区的方法是包括在解析函数调用划分;例如,在(分区的一年,other_columns other_analytic_clauses)。
1.1.5.3 动态分区修剪
原来的机制用于修剪分区是静态分区修剪,在其中的条件,在条款进行分析,以确定提前哪些分区可以安全地跳过。在Impala 2.5 /CDH5.7及更高版本,impala可以执行动态分区修剪,在分区信息中查询收集,和impala修剪不必要的分区方式是提前预测不切实际。
例如,如果分区键列进行比较的文字值WHERE子句中,impala可以执行静态分区修剪规划阶段在阅读相关的分区:
[mw_shl_code=text,true]-- Thequery only needs to read 3 partitions whose key values are known ahead of time.
-- That'sstatic partition pruning.
SELECTCOUNT(*) FROM sales_table WHERE year IN (2005, 2010, 2015);[/mw_shl_code]
动态分区修剪涉及使用信息只有在运行时,如查询结果:
[mw_shl_code=text,true]
createtable yy (s string) partitioned by (year int) stored as parquet;
insert intoyy partition (year) values ('1999', 1999), ('2000', 2000),
('2001', 2001), ('2010',2010);
computestats yy;
createtable yy2 (s string) partitioned by (year int) stored as parquet;
insert intoyy2 partition (year) values ('1999', 1999), ('2000', 2000),
('2001', 2001);
computestats yy2;
-- Thequery reads an unknown number of partitions, whose key values are only
-- known atrun time. The 'runtime filters' lines show how the information about
-- thepartitions is calculated in query fragment 02, and then used in query
-- fragment00 to decide which partitions to skip.
explainselect 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 |
+----------------------------------------------------------+[/mw_shl_code]
在这种情况下,impala评价子查询,子查询结果发送所有Impala节点参与查询,然后每个impalad守护进程采用动态分区剪枝优化与相关键值只读分区。
动态分区修剪是特别有效的查询,涉及几个大的分区表的联接。评估联接谓词的子句,通常需要从某些表的所有分区中读取数据。如果该查询的WHERE子句中引用的分区键列,impala现在经常可以跳过阅读许多的分区在评估条款。动态分区修剪优化减少了在查询过程中的网络存储和传输的I / O和中间数据量的量。
当溢出到磁盘功能是一个连接节点在查询激活,impala不产生任何运行过滤器,主机上的连接操作。查询中的其他连接节点不受影响。
动态分区修剪是运行时过滤功能的一部分,它适用于其他类型的查询,除了对分区表的查询。看到运行的impala查询有关此功能的详细的过滤。
1.1.6 分区键列
您选择的列作为分区键应该是经常用于筛选查询结果的重要的大型查询。流行的例子是一些组合的一年,一个月,和一天的数据有相关的时间值,和地理区域的数据时,与一些地方。
基于时间的数据,分离出独立的部分纳入自己的栏目,因为impala不能划分一个时间戳列。
该分区列的数据类型不具有对存储要求的效果显著,因为从这些列的值不存储在数据文件中,而他们是在HDFS目录名称的字符串。
在CDH 5.7 /impala2.5及更高版本,可以使optimize_partition_key_scans查询选项来加快查询的速度,仅指分区键列,如选择最大(年)。默认情况下,此设置没有启用,因为如果表中包含没有实际数据的分区目录,则查询的行为将略有不同。看到optimize_partition_key_scans查询详情。
分区表可以包含复杂的类型列。所有分区键列必须为标量类型。
记住,当impala查询存储在HDFS的数据,它是最有效的使用多字节的文件利用HDFS块大小。实木复合地板表,块的大小(和数据文件大小是理想)2 256 MB,后来impala。因此,避免指定太多的分区键列,这可能会导致单个分区只包含少量的数据。例如,如果你每天收到1个数据,你可能会被一年一个月,一天一天;而如果你每分钟收到5个数据,你可能会被一年、一个月、一天、一小时、一分钟划分。如果你与一个地理成分的数据,你可能会划分邮政编码,如果您有许多兆字节的每个邮政编码数据,但如果没有的话,你可能会被一些大的区域,如城市、州或国家划分。状态
如果你经常运行汇总等功能min(),max(),计数(不同的)分区键列,考虑启用optimize_partition_key_scans查询优化查询。这一特征在CDH 5.7 /impala2.5及更高版本可用。看到optimize_partition_key_scans查询选项,这个选项适用于查询的种类,和轻微的差异如何分区进行评估时,该查询选项启用。
1.1.7 设置分区的不同的文件格式
分区表有灵活性,使用不同的分区使用不同的文件格式。(关于不同的文件格式支持背景信息看,impala、impala和Hadoop文件格式。)例如,如果你在文本格式最初收到数据,然后接收新的数据格式,并最终开始RCFile,拼花格式接收数据,这些数据可以驻留在同一个表的查询。您只需要确保表的结构,以便使用不同的文件格式的数据文件驻留在单独的分区中。
例如,这里是你如何可以从文本到地板的数据你不同年接收数据:
[mw_shl_code=text,true][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 toParquet 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');[/mw_shl_code]
在这一点上,HDFS目录 year=2012包含一个文本格式的数据文件,而HDFS目录 year=2013包含一个复合数据文件。和总是一样,当加载不平凡的数据时,您将使用插入…选择或加载数据以大批量导入数据,而不是插入…值,产生小的文件,是低效的现实世界的查询。
对于其他类型的文件,impala不能创造本身,你可以切换到蜂巢的问题修改表…设置文件格式报表和报表数据插入或负载有。切换回Impala后,发出声明,刷新table_nameImpala承认任何分区或新添加的数据通过hive。
1.1.8 管理分区
你可以添加,删除,设定预期的文件格式,或一组数据文件HDFS位置个别分区impala表内。有关语法细节的更改表语句,并在包含分区的分区的管理表上设置不同的文件格式的不同的文件格式。
注:如果您正在创建一个分区,并指定它的位置,为最大效率,使用一个单一的更改表语句,包括添加分区和位置子句,而不是单独的语句与添加分区和设置位置子句。
当一个分区被删除时,数据文件会发生什么,取决于分区表是否被指定为内部或外部的。对于内部(托管)表,数据文件已被删除。例如,如果分区表中的数据是存储在其他地方的原始数据文件的副本,则可以通过删除不再需要的旧分区来保存磁盘空间,知道原始数据在需要时仍然可用。对于一个外部表,数据文件将被单独留下。例如,删除一个分区没有删除相关的文件让impala考虑更小的分区,提高查询效率和减少表的DDL操作的开销;如果数据再次需要后,你可以再添加分区。看到的细节和例子的impala表概述。
作者:DBA_Hadoop
来源:blog.csdn
|