在 Apache HIVE 中分区,更多问题
Partitioned by in Apache HIVE, more questions
这里有一些不错的questions/answers
hive subquery optimization using cluster by
What is the difference between partitioning and bucketing a table in Hive ?
但我还有一些,不幸的是24页这里没有很好的解释:
https://docs.hortonworks.com/HDPDocuments/HDP3/HDP-3.0.1/using-hiveql/hive_using_hiveql.pdf
我的问题:
在上面的例子中:
CREATE TABLE pageviews (userid VARCHAR(64), link STRING, from STRING)
PARTITIONED BY (datestamp STRING) CLUSTERED BY (userid) INTO 256 BUCKETS;
INSERT INTO TABLE pageviews PARTITION (datestamp = '2014-09-23') VALUES
('jsmith', 'mail.com', 'sports.com'), ('jdoe', 'mail.com', null);
INSERT INTO TABLE pageviews PARTITION (datestamp) VALUES ('tjohnson',
'sports.com', 'finance.com', '2014-09-23'), ('tlee', 'finance.com', null,
'2014-09-21');
为什么 "datestamp STRING" 不存在于综合浏览量的架构中?
为什么定义为字符串?不应该是时间戳?
为什么第二个插入会遗漏它并且只有它作为类型但它有值(即“2014-09-23”和“2014-09-21”?
为什么 "datestamp STRING" 不存在于综合浏览量的架构中?
尽管 datestamp 看起来和行为都像模式中定义的标准列,但它实际上只是对 table 基础数据的特定分区的引用。当您在日期戳列中看到“2014-09-23”时,它实际上并没有向您显示一个数据文件中特定记录中包含的值,而是告诉您该行其余部分的数据来自名为 'datestamp=2014-09-23' 的 HDFS 目录包含分区或 "chunk" 数据。这是大量的优化,因为过滤对特定分区的查询允许 Hive 简单地转到该特定目录中的数据并忽略其他 n 个分区中包含的数据。
为什么定义为字符串?应该是时间戳?
由于分区只是指目录名称,因此只有类型是特定日期格式的字符串表示而不是时间戳或日期才有意义。从概念上讲,日期字段没有意义,因为尽管“2014-09-23”和“9/23/2014”是两个相同的日期戳,但如果它们是目录名称,它们将被视为不同的目录。换句话说,如果一个目录名为“2014-09-23”,则您不能使用任何其他名称来引用它,这使它更像一个字符串,而不像一个日期,它有许多等价的替代形式。此外,Hive 已经将日期视为字符串,这使其成为比 int 类型更好的解决方案。例如,如果您将时间戳传递给 Hive 的 to_date() 用户定义函数,它将 returns 日期作为字符串。
此外,由于您提到了时间戳,使用包含几分之一秒的完整时间戳对于分区来说不是一个好主意,即使您使用它的字符串表示形式也是如此。您最终会得到大量的分区,每个分区中可能只有一条或最多只有几条记录。我想您会很快失去分区的任何性能优势。
为什么第二个插入会遗漏它并且只有它作为类型但它有值(即'2014-09-23'和'2014-09-21?
这只是产生相同结果的不同语法。当您包含分区时,Hive 将假定 values 数组末尾的值引用分区。因此,如果您的 table 在您的架构中有 3 列和 1 个分区,当您执行 insert into table 命令并指定 partition (datestamp),你可以只传入 4 个值,Hive 会知道前 3 个值将被插入到你的 schema 中的 3 列中,第四个值是指你要添加哪个 datestamp 分区这条记录的数据到.
这里有一些不错的questions/answers
hive subquery optimization using cluster by
What is the difference between partitioning and bucketing a table in Hive ?
但我还有一些,不幸的是24页这里没有很好的解释: https://docs.hortonworks.com/HDPDocuments/HDP3/HDP-3.0.1/using-hiveql/hive_using_hiveql.pdf
我的问题:
在上面的例子中:
CREATE TABLE pageviews (userid VARCHAR(64), link STRING, from STRING)
PARTITIONED BY (datestamp STRING) CLUSTERED BY (userid) INTO 256 BUCKETS;
INSERT INTO TABLE pageviews PARTITION (datestamp = '2014-09-23') VALUES
('jsmith', 'mail.com', 'sports.com'), ('jdoe', 'mail.com', null);
INSERT INTO TABLE pageviews PARTITION (datestamp) VALUES ('tjohnson',
'sports.com', 'finance.com', '2014-09-23'), ('tlee', 'finance.com', null,
'2014-09-21');
为什么 "datestamp STRING" 不存在于综合浏览量的架构中?
为什么定义为字符串?不应该是时间戳?
为什么第二个插入会遗漏它并且只有它作为类型但它有值(即“2014-09-23”和“2014-09-21”?
为什么 "datestamp STRING" 不存在于综合浏览量的架构中?
尽管 datestamp 看起来和行为都像模式中定义的标准列,但它实际上只是对 table 基础数据的特定分区的引用。当您在日期戳列中看到“2014-09-23”时,它实际上并没有向您显示一个数据文件中特定记录中包含的值,而是告诉您该行其余部分的数据来自名为 'datestamp=2014-09-23' 的 HDFS 目录包含分区或 "chunk" 数据。这是大量的优化,因为过滤对特定分区的查询允许 Hive 简单地转到该特定目录中的数据并忽略其他 n 个分区中包含的数据。
为什么定义为字符串?应该是时间戳?
由于分区只是指目录名称,因此只有类型是特定日期格式的字符串表示而不是时间戳或日期才有意义。从概念上讲,日期字段没有意义,因为尽管“2014-09-23”和“9/23/2014”是两个相同的日期戳,但如果它们是目录名称,它们将被视为不同的目录。换句话说,如果一个目录名为“2014-09-23”,则您不能使用任何其他名称来引用它,这使它更像一个字符串,而不像一个日期,它有许多等价的替代形式。此外,Hive 已经将日期视为字符串,这使其成为比 int 类型更好的解决方案。例如,如果您将时间戳传递给 Hive 的 to_date() 用户定义函数,它将 returns 日期作为字符串。
此外,由于您提到了时间戳,使用包含几分之一秒的完整时间戳对于分区来说不是一个好主意,即使您使用它的字符串表示形式也是如此。您最终会得到大量的分区,每个分区中可能只有一条或最多只有几条记录。我想您会很快失去分区的任何性能优势。
为什么第二个插入会遗漏它并且只有它作为类型但它有值(即'2014-09-23'和'2014-09-21?
这只是产生相同结果的不同语法。当您包含分区时,Hive 将假定 values 数组末尾的值引用分区。因此,如果您的 table 在您的架构中有 3 列和 1 个分区,当您执行 insert into table 命令并指定 partition (datestamp),你可以只传入 4 个值,Hive 会知道前 3 个值将被插入到你的 schema 中的 3 列中,第四个值是指你要添加哪个 datestamp 分区这条记录的数据到.