[关闭]
@hadoopMan 2018-01-11T11:19:14.000000Z 字数 6829 阅读 948

join

Join 语法

Hive支持连接表的以下语法:

  1. join_table:
  2. table_reference [INNER] JOIN table_factor [join_condition]
  3. | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition
  4. | table_reference LEFT SEMI JOIN table_reference join_condition
  5. | table_reference CROSS JOIN table_reference [join_condition] (as of Hive 0.10)
  6. table_reference:
  7. table_factor
  8. | join_table
  9. table_factor:
  10. tbl_name [alias]
  11. | table_subquery alias
  12. | ( table_references )
  13. join_condition:
  14. ON expression

例子

编写连接查询时要考虑的一些要点如下:

  1. SELECT a.* FROM a JOIN b ON (a.id = b.id)
  1. SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
  1. SELECT a.* FROM a LEFT OUTER JOIN b ON (a.id <> b.id)

是有效的连接。

  1. SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)

是一个有效的连接。

  1. SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)

被转换成一个map / reduce作业,因为只有b的key1列参与了连接。另一方面

  1. SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)

被转换成两个map / reduce作业,因为来自b的key1列在第一个连接条件中使用,而来自b的key2列在第二个连接条件中使用。第一个map / reduce作业与b连接,然后在第二个map / reduce作业中将结果与c连接。

  1. SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)

所有这三个表都加入到一个map / reduce作业中,表a和b的键的特定值的值被缓存在reducer的内存中。然后,对于从c中检索的每一行,都会使用缓冲的行计算连接。同样的

  1. SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)

有两个map / reduce参与计算连接。其中的第一个和b一起加入一个缓冲区,并缓存一个值,同时在reducers中传送b的值。其中一个作业的第二个缓冲了第一个连接的结果,同时通过reducer传送了c的值。

  1. SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)

所有这三个表都加入到一个map / reduce作业中,并且表b和c的键的特定值的值被缓存在reducer中的内存中。然后,对于从a中检索的每一行,都会使用缓冲的行计算连接。如果省略了STREAMTABLE提示,则Hive会将最右边的表格加入连接。

  1. SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)

将返回一行中的每一行。当有一个等于a.key的b.key时,这个输出行将是a.val,b.val,当没有相应的b.key时,输出行将是a.val,NULL。从没有对应的a.key的行将被删除。语法“FROM LEFT OUTER JOIN b”必须写在一行上,以便理解它是如何工作的 - a是在这个查询中b的左边,所以a中的所有行都保留; RIGHT OUTER JOIN将保留来自b的所有行,并且FULL OUTER JOIN将保留来自b的所有行的所有行。OUTER JOIN语义应该符合标准的SQL规范。

  1. SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
  2. WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

将加入b,产生a.val和b.val的列表。但是,WHERE子句也可以引用连接输出中的a和b的其他列,然后将其过滤掉。但是,每当JOIN的某行为b找到一个键而没有键时,b的所有列都将为NULL,包括ds列。这就是说,你将过滤掉没有有效的b.key的所有连接输出行,因此你已经超出了你的LEFT OUTER要求。换句话说,如果在WHERE子句中引用b的任何一列,则连接的LEFT OUTER部分是无关紧要的。相反,当外部连接时,使用下面的语法:

  1. SELECT a.val, b.val FROM a LEFT OUTER JOIN b
  2. ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')

结果是连接的输出被预先过滤,并且您将不会得到有一个有效的a.key但没有匹配的b.key行的后过滤的麻烦。相同的逻辑适用于右和全连接。

  1. SELECT a.val1, a.val2, b.val, c.val
  2. FROM a
  3. JOIN b ON (a.key = b.key)
  4. LEFT OUTER JOIN c ON (a.key = c.key)

首先加入一个B,丢弃在其他表中没有相应的键的a或b中的所有内容。缩小的表然后在c上结合。这提供了不直观的结果,如果在a和c中都存在一个键,但不是b:整个行(包括a.val1,a.val2和a.key)在“a JOIN b”步骤中被删除,因为它不在b。结果没有a.key,所以当它与L是外部连接的时候,c.val没有进入,因为没有与a.key相匹配的c.key(因为a的那一行被删除了)。同样,如果这是一个RIGHT OUTER JOIN(而不是LEFT),我们最终会得到一个更奇怪的效果:NULL,NULL,NULL,c.val,因为即使我们指定了a.key = c.key作为连接键,我们删除了与第一个JOIN不匹配的所有行。
为了达到更直观的效果,我们应该做一个ON(c.key = a.key)LEFT OUTER JOIN b ON(c.key = b.key)。

  1. SELECT a.key, a.value
  2. FROM a
  3. WHERE a.key in
  4. (SELECT b.key
  5. FROM B);

可以改写为:

  1. SELECT a.key, a.val
  2. FROM a LEFT SEMI JOIN b ON (a.key = b.key)
  1. SELECT /*+ MAPJOIN(b) */ a.key, a.value
  2. FROM a JOIN b ON a.key = b.key

不需要reduce。对于A的每个映射器,B都被完全读取。限制是不能执行FULL / RIGHT OUTER JOIN b。

  1. SELECT /*+ MAPJOIN(b) */ a.key, a.value
  2. FROM a JOIN b ON a.key = b.key

只能在mapper上完成。不是为每个A的映射器完全获取B,而只是获取所需的桶。对于上面的查询,A的映射器处理存储桶1将仅取出B的桶1.它不是默认的行为,并由以下参数

  1. set hive.optimize.bucketmapjoin = true
  1. SELECT /*+ MAPJOIN(b) */ a.key, a.value
  2. FROM A a JOIN B b ON a.key = b.key

只能在mapper上完成。A的桶的映射器将遍历B的相应桶。这不是默认行为,需要设置以下参数:

  1. set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
  2. set hive.optimize.bucketmapjoin = true;
  3. set hive.optimize.bucketmapjoin.sortedmerge = true;

排序

摘录译自:
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy

Order, Sort, Cluster, and Distribute By

这描述了SELECT子句的ORDER BY,SORT BY,CLUSTER BY和DISTRIBUTE BY的语法。

Order By的语法

Hive QL中的ORDER BY语法类似于SQL语言中ORDER BY的语法。

  1. colOrder: ( ASC | DESC )
  2. colNullOrder: (NULLS FIRST | NULLS LAST) -- (Note: Available in Hive 2.1.0 and later)
  3. orderBy: ORDER BY colName colOrder? colNullOrder? (',' colName colOrder? colNullOrder?)*
  4. query: SELECT expression (',' expression)* FROM src orderBy

“order by”子句有一些限制。在严格模式(即,hive.mapred.mode = strict)中,order by子句必须后跟一个“limit”子句。如果将hive.mapred.mode设置为nonstrict,则不需要limit子句。原因是为了强加所有结果的总顺序,必须有一个reducer来排序最终的输出。如果输出中的行数太大,单个减速器可能需要很长时间才能完成。
请注意,列是按名称指定的,而不是按位置编号指定的。但是,在Hive 0.11.0及更高版本中, 按以下方式进行配置时,可以按位置指定列:

默认的排序顺序是升序(ASC)。
在Hive 2.1.0和更高版本中,支持在“order by”子句中为每个列指定空排序顺序。ASC顺序的缺省排序顺序为NULLS FIRST,而DESC顺序的缺省排序顺序为NULLS LAST。

在Hive 3.0.0及更高版本中,优化程序将删除子查询和视图中无限制的顺序。要禁用它,请将hive.remove.orderby.in.subquery设置 为false。

Sort By的语法

该排序语法类似于语法ORDER BY在SQL语言。

  1. colOrder: ( ASC | DESC )
  2. sortBy: SORT BY colName colOrder? (',' colName colOrder?)*
  3. query: SELECT expression (',' expression)* FROM src sortBy

ive使用SORT BY中的列对行进行排序,然后将这些行传送给还原器。排序顺序将取决于列类型。如果该列是数字类型,那么排序顺序也是按数字顺序排列的。如果该列是字符串类型,那么排序顺序将是字典顺序。
在hive 3.0.0或更高版本,排序没有限制 的子查询 和 意见 将被优化去除。要禁用它,请将hive.remove.orderby.in.subquery设置 为false。

Sort By and Order By的区别

Hive支持对每个Reducer数据进行排序的SORT BY。“order by”和“sort by”之间的区别在于,前者保证输出中的总顺序,而后者只保证缩减器内的行的顺序。如果有多个还原剂,“排序”可能会给出部分有序的最终结果。

注意:可能会混淆SORT BY单独列和CLUSTER BY之间的区别。不同之处在于,CLUSTER BY按字段进行分区,如果有多个reducer分区,则为SORT BY,以便在整个还原器中统一分配数据(和加载)。

基本上,每个reducer中的数据将按照用户指定的顺序进行排序。以下示例显示

  1. SELECT key, value FROM src SORT BY key ASC, value DESC

查询有2个reducer,每个的输出是:

  1. 0 5
  2. 0 3
  3. 3 6
  4. 9 1
  1. 0 4
  2. 0 3
  3. 1 1
  4. 2 5

Sort By设置方式

变换之后,变量类型通常被认为是字符串,这意味着数字数据将按字典顺序排序。为了克服这个问题,可以在使用SORT BY之前使用第二个带有强制转换的SELECT语句。

  1. FROM (FROM (FROM src
  2. SELECT TRANSFORM(value)
  3. USING 'mapper'
  4. AS value, count) mapped
  5. SELECT cast(value as double) AS value, cast(count as int) AS count
  6. SORT BY value, count) sorted
  7. SELECT TRANSFORM(value, count)
  8. USING 'reducer'
  9. AS whatever

Cluster By and Distribute By的语法

Cluster By和Distribution By主要用于Transform / Map-Reduce脚本。但是,如果需要对后续查询的查询输出进行分区和排序,则在SELECT语句中有时会很有用。

Cluster By是Distribute By和Sort By的缩写。

Hive使用Distribute By中的列在reducer中分配行。具有相同“ 分布依据”列的所有行将转到同一个还原器。但是,“ 分发依据”不保证对分布式密钥进行集群或排序属性。

例如,我们在以下5行中将x分配给2个reducer:

  1. x1
  2. x2
  3. x4
  4. x3
  5. x1

reducer1得到

  1. x1
  2. x2
  3. x1

reducer2得到

  1. x4
  2. x3

用户可以指定“ Distribute By” 和“ Sort By,” ,而不是指定“ Cluster By” ,因此分区列和排序列可以不同。通常情况下,分区列是排序列的前缀,但这不是必需的。

  1. SELECT col1, col2 FROM t1 CLUSTER BY col1
  1. SELECT col1, col2 FROM t1 DISTRIBUTE BY col1
  2. SELECT col1, col2 FROM t1 DISTRIBUTE BY col1 SORT BY col1 ASC, col2 DESC
  1. FROM (
  2. FROM pv_users
  3. MAP ( pv_users.userid, pv_users.date )
  4. USING 'map_script'
  5. AS c1, c2, c3
  6. DISTRIBUTE BY c2
  7. SORT BY c2, c1) map_output
  8. INSERT OVERWRITE TABLE pv_users_reduced
  9. REDUCE ( map_output.c1, map_output.c2, map_output.c3 )
  10. USING 'reduce_script'
  11. AS date, count;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注