这里有一些很好的问题/答案
在多个列上按群集的配置单元
基于聚类的hive子查询优化
Hive中的“群集方式”和“群集方式”之间的区别?
在配置单元中对表进行分区和bucketing有什么区别?
但我还有一些,不幸的是,第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');
为什么页面视图的模式中不存在“日期戳字符串”?
为什么它被定义为字符串?不应该是时间戳?
为什么第二个insert会漏掉它,并且只将它作为类型,而将它作为值(即“2014-09-23”和“2014-09-21”)?
1条答案
按热度按时间6pp0gazn1#
为什么页面视图的模式中不存在“日期戳字符串”?
尽管datestamp的外观和行为类似于模式中定义的标准列,但它实际上只是对表的基础数据的特定分区的引用。当您在datestamp列中看到'2014-09-23'时,它实际上并没有向您显示其中一个数据文件中特定记录中包含的值,而是告诉您行其余部分的数据来自名为'datestamp=2014-09-23'的hdfs目录,该目录包含数据的分区或“块”。这是一个很大的优化,因为过滤一个查询到一个特定的分区允许配置单元简单地转到那个特定目录中的数据,而忽略其他n个分区中包含的数据。
为什么它被定义为字符串?应该是时间戳吗?
因为分区只是引用一个目录名,所以类型是特定日期格式的字符串表示形式而不是时间戳或日期才有意义。从概念上讲,日期字段没有意义,因为虽然“2014-09-23”和“9/23/2014”是两个相等的日期戳,但如果它们是目录名,则它们将被视为不同的目录。换句话说,如果一个目录名为'2014-09-23',您不能用任何其他名称来引用它,使它更像一个字符串,而不像一个日期,它有许多替代形式都是等价的。此外,hive已经将日期视为字符串,这使得它比int类型更好的解决方案。例如,如果您将时间戳传递给hive的to_date()用户定义函数,它将以字符串形式返回日期。
另外,既然您提到了时间戳,那么使用一个完整的时间戳(时间戳中只有几秒钟)对于分区来说是个坏主意,即使您使用了它的字符串表示。最终会有大量的分区,每个分区中可能只有一条或最多只有几条记录。我可以想象您很快就会失去分区的任何性能优势。
为什么第二个insert会漏掉它,并且只将它作为类型,而将它作为值(即“2014-09-23”和“2014-09-21”)?
这只是产生相同结果的不同语法。包含分区时,配置单元将假定值数组末尾的值引用分区。因此,如果您的模式中有一个表,其中有3列和1个分区,那么当您执行insert into table命令并指定partition(datestamp)时,只需传入4个值,hive就会知道前3个值将被插入模式中的3列,第四个值是指要将此记录的数据添加到哪个日期戳分区。