第7章 HiveQL:视图
** 7.1 使用视图来降低查询复杂度**
** 7.2 使用视图来限制基于条件过滤的数据**
** 7.3 动态分区中的视图和map类型**
第8章 HiveQL:索引
第9章 模式设计
** 9.1 按天划分的表**
** 9.2 关于分区**
HDFS用于设计数百万的大文件,而非数十亿的小文件。使用过多的分区可能导致的问题是会创建大量的非必须的Hadoop文件和文件夹。一个分区就对应着一个包含有多个文件的文件夹。如果指定的表存在数百个分区,那么可能每天都会创建好几万个文件。如果保持这样的表很多年,那么最终就会超出NameNode对系统云数据信息的处理能力。因为NameNode必须要将所有的系统文件的元数据信息保存在内存里。
MapReduce会将一个任务(job)转换成多个任务(task)。默认情况下,每个task都是一个新的JVM实例,都需要开启和销毁的开销。
** 9.3 唯一键和标准化**
关系型数据库通常使用唯一键、索引和标准化来存储数据集,通常是全部或者大部分存储到内存。然而,Hive没有主键或者基于序列密钥生成的自增键的概念。如果可以的话,应避免对非标准化数据进行连接(JOIN)操作。复杂的数据类型,如array、map和struct,有助于实现在单行中存储一对多数据。
避免标准化的主要原因是为了最小化磁盘寻道,比如那些通常需要外键关系的情况。非标准化数据允许被扫描或写入到大的、连续的磁盘存储区域,从而优化磁盘驱动器的I/O性能。然而,非标准化数据可能导致数据重复,而且有更大的导致数据不一致的风险。
CREATE TABLE IF NOT EXISTS mydb.employees (
name STRING COMMENT 'Employee name',
salary FLOAT COMMENT 'Employee salary',
subordinates ARRAY<STRING> COMMENT 'Names of subordinates',
deductions MAP<STRING,FLOAT> COMMENT 'Keys are deductions names,values are percentages',
address STRUCT<street:STRING,city:STRING,state:STRING>
COMMENT 'Home address')
这个例子中的数据模型从很多方面打破了传统的设计原则。
首先,我们非正式地使用name作为主键。一个关系模型中如果使用name作为键,那么从一个员工记录到经理记录应该有唯一的一个外键关系。这里我们使用另一种方式来表达这个关系,即在subordinates数组字段中保存了这个员工所有的下属的名字。
其次,对于每名员工来说,其各项税收扣额都是不同的,但是map的键是一样的,一个常规的关系模型通常使用一个单独的、具有2个列的表来记录税收扣除项的扣除名称和具体的值,而员工表和这个税收扣除项之间是一对多的关系。
最后,有些雇员可能住在同一个地址,但是我们为每个雇员都记录了其对应的住址,而不是使用一个雇员住址表,然后和雇员表建立了一对一的关系。
** 9.4 同一份数据多种处理**
Hive 可以从一个数据源产生多个数据聚合,而无需每次聚合都要重新扫描一次。
** 9.5 对于每个表的分区**
很多的ETL处理过程会涉及到多个处理步骤,而每个步骤可能会产生一个或多个临时表,这些表仅供下一个job使用。对于临时表进行分区的应用场景:由于查询或者原始数据处理的某个步骤出现问题而导致需要对好几天的输入数据重跑ETL过程。
** 9.6 分桶表数据存储**
分桶是将数据集分解成更容易管理的若干部分的另一个技术。
例如,假设有个表的一级分区是dt,代表日期,二级分区是user_id,那么这种划分方式可能会导致太多的小分区。回想下,如果用户使用动态分区来创建这些分区的话,那么默认情况下,Hive会限制动态分区可以创建的最大分区数,用来避免由于创建太多的分区导致超过了文件系统的处理能力。
hive > CREATE TABLE weblog (url STRING , source_ip STRING)
> PARTITIONED BY(dt STRING, user_id INT);hive > FROM raw_weblog
> INSERT OVERWRITE TABLE page_view PARTITION (dt=‘2012-06-09’ ,user_id )
> SELECT server_name,url,source_ip,dt,user_id;
不过,如果我们对表weblog进行分桶,并使用user_id字段作为分桶字段,则字段值会根据用户指定的值进行哈希分发到桶中。同一个user_id下的记录通常会存储到同一个桶内。
hive > CREATE TABLE weblog (user_id INT, url STRING,source_ip STRING)
> PARTITIONED BY (dt STRING)
> CLUSTERED BY (user_id) INTO 96 BUCKETS;