对那些使用传统数据库的用户来说,Hive看上去和使用上都很向传统的关系型数据库:有相似的命名法,和传统SQL特别是MySQL方言很相似的HiveQL方言,然而Hive在实现上和使用上都和之前的传统数据库有很大的不同。通常情况下,用户尝试使用关系数据库世界的范式,实际上是Hive反模式。
本节我们重点介绍一些用户可能已使用过的模式和尽量要避免的反模式。
Table-by-Day
Table-by-Day是一个被定义为
“表名 + 日期”的Hive表的模式,比如supply_2013-05-19、supply_2013-05-20等。
Table-by-Day在数据库世界中是一个反模式,但是面对日益增长的数据集,它仍然被广泛使用:
hive> CREATE TABLE supply_2013_05_18(ind INT,part STRING,quantity INT);
hive> CREATE TABLE supply_2013_05_19(ind INT,part STRING,quantity INT);
hive> CREATE TABLE supply_2013_05_20(ind INT,part STRING,quantity INT);
hive> ... load data ...
hive> SELECT part,quantity FROM supply_2013_05_18
> UNION ALL
> SELECT part,quantity FROM supply_2013_05_19
> WHERE quantity < 4;
这种情况下,应该使用分区表来替换这种Table-by-Day的表设计,通过日期来将数据分区,然后在查询时指明只查询的具体分区中的数据,这种查询不仅更高效,而且HiveQL语句看上去简洁又情绪:
hive> CREATE TABLE supply(ind INT,part STRING,quantity INT)
> PARTITIONED BY (day INT);
hive> ALTER TABLE supply ADD PARTITION (day=20130518);
hive> ALTER TABLE supply ADD PARTITION (day=20130519);
hive> ALTER TABLE supply ADD PARTITION (day=20130520);
hive> ... load data ...
hive> SELECT part,quantity FROM supply
> WHERE day >= 20130518 AND day < 20130520 AND quantity < 4;
过度分区(Over Partitioning)
在Hive中,表的分区功能非常有用,因为在通常情况下Hive执行HiveQL查询时是全表扫描的(这里我们先不考虑Hive索引)。然而,如果创建了太多的分区,虽然会优化某些查询,但也会对其他查询不利:
hive> CREATE TABLE weblogs(url STRING,time long)
> PARTITIONED BY(day INT,state STRING,city STRING);
hive> SELECT * FROM weblogs WHERE day=20130519;
Hadoop HDFS被设计为适合存储数以百万计的大文件,而不是数十亿的小文件。首先,创建太多的跟去也就意味着大量的文件目录和更多的文件是不必要的,因为一个分区目录中通常有很多的文件。如果一个分区表包含上千的分区并且每天都新增很多数据的话,那么这个表就有可能会有每天上千个分区和上万个数据文件,然后每年...,最终会突破Hadoop NameNode的最大内存限制。
我们知道,HiveQL语句最终被编译为MapReduce程序,被提交到Hadoop上作为job作业执行,然后JobTracker会分解成许多的task,在没有设置JVM重用的情况下,每一个task都会启用一个新的JVM进程,这会产生巨大的JVM的初始化和销毁的开销,从而增大整个作业执行时间。
因此,一个理想的分区模式应该不会导致太多的分区和目录,每个目录中的文件应该要大——最好是HDFS block块大小的倍数。
对一个有时间范围分区要求的表,一个比较好的策略就是根据不同的时间段内数据增长的近似大小,燃气分区和数据随着时间“温和”的增长,并且“保证”数据文件的的生成时间顺序和大小大致为HDFS block块大小的数倍。这会保证分区大而均衡,从而达到对一般情况下查询的优化:
hive> CREATE TABLE weblogs(url STRING,time LONG,state STRING,city STRING)
hive> PARTITIONED BY(day INT);
hive> SELECT * FROM weblogs WHERE day=20130519;
另一个解决方案就是使用两个不同级别的分区。比如,第一级分区是日期,第二级分区可以是一个地理上的地区如:
hive> CREATE TABLE (url STRING,time LONG,city STRING)
> PARTITIONED BY(day INT,state STRING);
hive> SELECT * FROM weblogs WHERE day=20130519;
唯一键和规范化(Unique Keys and Normalization)
Hive不像传统的关系型数据库中通常使用唯一键、索引和规范化的数据,它没有主键以及自增长主键的概念,在Jion连接中应尽量避免非规范化的数据。对于Hive的复杂数据类型如Array、Map和Struct,这些一对多的数据可以被保存在Hive的一行中,这并不是说这些复杂类型不应该被使用,但是这种星型结构的设计并非最佳。
在Hive中使用复杂数据类型设计(避免正规化)的主要原因是尽量减少磁盘的查找时间。
Making Multiple Passes Over the Same Data
实在不知道
Making Multiple Passes Over the Same Data怎么翻译,大致意识就是在从一个数据源表中向多个表中倒数据时,最好只扫描一次数据源而将数据导入多个不同的表中。
比如下例中,每一行都是从数据源表history中倒数据:
hive> INERT OVERWRITE TABLE sales
> SELECT * FROM history WHERE action='purchased';
hive> INERT OVERWRITE TABLE credits
> SELECT * FROM history WHERE action='returned';
上例中的HiveQLs语句语法是正确的,但是低效,因为每个HiveQL语句都会执行一次全表扫描,最好将上例中的两个HiveQL语句合并成一个HiveQL:
hive> FROM history
> INSERT OVERWRITE sales SELECT * WHERE action='purchased'
> INSERT OVERWRITE credits SELECT * WHERE action='returned';
这种写法只会执行一次全表扫描,高效。
使用桶表做数据存储(Bucketing Table Data Storage)
Hive的分区功能提供了一种方便的方式来区分数据和优化查询。然而,并不是所有的数据都可以做合理的分区的,特别是在分区中数据不均衡的情况下更是如此。
将数据分桶是另一项奖大数据集分解成多个便于管理的文件的技术。例如,假设有一个使用日期dt作为一级分区和user_id作为二级分区的表,这种设计会导致很多小的分区,想象一下如果您动态创建这些分区,(默认情况下)Hive会限制创建最大的动态分区的数量,太多的分区有可能会突破NameNode物理内存的最大限制和其他问题,所以线面的HiveQL执行可能失败:
hive> CREATE TABLE weblog(url STRING,source_ip STRING)
> PARTITIONED BY(dt STRING,user_id STRING);
hive> FROM raw_weblog
> INSERT OVERWRITE TABLE weblog PARTITION(dt='2012-06-08',user_id)
>SELECT url,source_ip,dt,user_id;
我们可以将上例的二级分区表改为桶表:
hive> CREATE TABLE weblog(user_id SRTING,url STRING,source_ip STRING)
hive> PARTITIONED BY(dt STRING)
hive> CLUSTERED BY(user_id) INTO 98 BUCKETS;
hive> SET hive.enforce.bucketing=true;
hive> FROM raw_logs
> INSERT OVERWRITE TABLE weblog
> PARTITION(dt='2012-08-28')
> SELECT user_id,url,source_ip WHERE dt='2012-08-28';
桶表还有一个比较有用的功能,那就是数据取样(Sampling)。
使用列表
见
深入学习《Programing Hive》:RCFile
(Almost) Always use Compresssion
分享到:
相关推荐
Design. Designed for a first Computer Science (CS1) C++ course, this text provides a breath of fresh air to you and your students. The CS1 course serves as the cornerstone of the Computer Science ...
HIVE编程指南中文版,是由programing hive翻译过来
电子书,djvu格式。 代码大全推荐的。 代码大全的作者这样说 “我从这本书里学到的有关软件设计的好点子和我从所有读过的其他书中学到的一样多。Plauger精通大量的设计方法,他很注重实效,同时也是个伟大的作家。”
在编程领域,编程1通常指的是初学者阶段的学习与实践,主要涵盖了基础的编程概念、语法和逻辑思维。在这个“编程的最终评估1”中,我们可以期待一个总结性的任务或者项目,目的是检验学习者对基本编程知识的理解和...
Hive编程指南中文版翻译,Hive programing
只要它可以帮助正在学习新算法的人,它是否从某个地方复制并不重要。 图形示例也将非常有帮助。 不要忘记包括测试。 不要删除以前的算法实现。 只需使用您自己的实现添加一个新文件。 美化和清理您的代码以便于阅读...
《Programming with MFC》是关于Microsoft Foundation Classes (MFC) 的编程指南,MFC 是微软为Windows应用程序开发提供的...通过深入学习MFC,开发者可以更好地理解和控制Windows应用程序的生命周期,提高开发效率。
azure-hive描述:“如何使用Azure蜂巢,如何编写脚本以及如何使用python预处理数据。” urlFragment: #this-用于与蜂巢接口中的蜂巢连接 直线-u'jdbc:hive2:// headnodehost:10001 /; transportMode = ...
c++ programingc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ programing and cc++ ...
在"visualization-programing:这是个人毕业设计"项目中,我们可以推测这是一个使用TypeScript语言实现的可视化编程工具或平台。 TypeScript是JavaScript的一个超集,由微软开发,旨在提供静态类型检查、类和模块等...
"vc_programing_style.rar_style" 提供了一个关于C++程序设计模式的资源,主要包含了一个名为"C++程序设计模式简介.pdf"的文档。这份资料可能详细介绍了如何在C++编程中应用和理解设计模式,以提升代码的可读性、可...
"Algorithm-competitive-programming.zip"这个压缩包文件,显然是为了帮助学习者深入理解和掌握算法以及如何在竞争编程中运用它们。让我们一起探讨其中蕴含的知识点。 1. **算法基础**:算法是一系列精确的步骤,...
你将深入理解编程的基本概念,精通Python语言,同时掌握算法与数据结构的核心知识,这些都是在各类编程竞赛中取得好成绩的关键。 【详细知识点】: 1. **Python基础**:Python因其简洁明了的语法和强大的库支持而...
《游戏编程模式》是Robert Nystrom所著的一本关于游戏开发的专业书籍,它深入探讨了在游戏开发中广泛使用的各种设计模式和技术。这本书旨在帮助游戏开发者提高代码的可读性、可维护性和复用性,使游戏项目更加高效、...
以上只是Python编程中的一些基础知识点,Python的生态庞大,还有更多高级特性和框架,如网络编程、并发处理、网络爬虫、机器学习、深度学习等,都需要进一步深入学习。Python-programing-main这个压缩包可能包含了...
《C++程序设计教程》是一本深入浅出的C++编程指南,专为那些希望掌握这一强大编程语言的初学者和进阶者设计。作者钱能以其丰富的教学经验和深厚的编程功底,为读者呈现了一部内容全面、实例丰富的C++学习宝典。 C++...
C语言是一种通用的高级编程语言,于1972年由丹尼斯·里奇为UNIX操作系统设计开发。C语言具有简洁性、高效性和灵活性等特点,被广泛应用于系统软件、应用程序、嵌入式系统等领域。 #### 2. C语言的基本结构 C语言...