开发者学堂课程【高校精品课-上海交通大学-企业级应用体系架构:HBase&Hive 2】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/75/detail/15847
HBase&Hive 2(一)
内容介绍:
一、Hive 是什么
二、读模式与写模式
三、artitions and buckets 分区和桶
四、常用的语法
五、云计算
一、Hive 是什么
1.简介
Hive 是什么? Hive 是在 Hadoop 之上建立的数据仓库。数据仓库为能够把各种的数据整合到里面统一地去处理。因此它和数据库的区别是其支持的数据来源一般有多个,关系型数据库以及关系型数据库里的表,数据源来自 PDF 文件、 CSV 文件等等,它整合到数据仓库里以后,体现出来的效果为立体的,不像关系型数据库那样是二维的数据,它可以在里面去做各个维度的切片分析,因此这是 Hive 的基本的用法。
在把数据导进Hive 之后,它提供了一种类似于 SQL 的语句,它叫 HQL 其中 H 是 Hive 的意思,为 Hive 的一种像 SQL 的一种语句,可以在上面进行查询。
整个 Hive 也像 HBase 一样,它是存储在 HDFS 之上。 HDFS 储存文件实际上是被切分为了很多小文件,每一位很多,这些块在存储到 Linux 上或者是底层的其它文件系统上时为一个个小文件, HDFS 即管理大文件和小文件之间的映射关系,这为所谓的 Hive 。
Hive 会把导进来的多种数据源的数据存储到它的一种叫表里面。它在表上面可以作为像 MapReduce 这样的并行的操作。因此可以在 Hadoop 的集群上去执行 MapReduce 操作。操作为类似 SQL 的查询,它把 SQL 的查询就转换为一组 Hadoop 集群之上,因此会比较快。它里面这些表就有元数据去描述它( schema ) 这些信息就存在整个数据库里面称为 metastore 的库里。因此这和关系型数据库很像,有专门的库去存所有其它的库中的一些元数据,主要是在存储库和表的 schema 下面为具体的例子。
2.例子
与前面我们讲 hadoop 所看到的那个天气预报的数据类似,因为它是组织为表的因此可以在 Hive 里面去用类似于创建表的语句来创建。
create table + name 。由于它不是关系型数据库。存储时,它不像关系型数据库那样做一系列,它可以按行存储,按列存储等等。可以直接指定银行的。记录是按照行来进行,一行表示一条记录。在这条记录里面,有三列为域,用 tab 键分隔。因此它和关运营数据库里面不太一样。在关系型数据库里面,我们只需要指定到这里。
当然还有主键或者是其它键,都是在描述这表的它的 schema 不会去描述底下这两块。
在关系型数据库里面,实际上是按列存储还是按行存储,这件事情是透明的,不需要管,假设想自己创建支持按列存储的关系型数据库,那么不需要去对 SQL 的语句做任何修改,因为 SQL 的语句本身没有指定这些它是透明的,用户不需要关心。
但在 Hive 的世界里面,它就不是这样, Hive 要去管理和说明。因此它在这里会说清楚,是按行存储,行里面的每一列按制表符去区分,
这样就可以看到,那它的数据库类似纯文本的数据库,它是在用这种方式存储内容。
3.内容从哪里来?
前面只是定整理好了一张表,这张表实际上是空的。如果要把这张表里的内容给填进去,那可以用导入的方式为它加载。它加载的后面是表示要加载的文件在哪里。例如是 sample.txt 文件,加载进来时去把这张表里已有的内容覆盖掉。
后半部分和关系型数据库很像,前面的是在指定要从哪个文件里导数据。那么导进来时,那它可能不是 TXT 的,是 PDF 的或者 CSV 的,则将要有相应的一些适配器去读它们,按照刚才定义的表格的结构去把表存进去。即一行表示一条记录,字段之间是靠制表键制表符来区分。
还要注意的一点是,这条语句只是在告诉 Hive 把文件加载到数据仓库的目录里头。刚才创建表时,实际上是在数据仓库里面创建了表,在加载它时,实际上它只是把文件放到了数据仓库的目录里面。放进来时。
没有去解析文件内容,例如年份温度和温气还没有解析出来,也没有真正存为刚才那个表的格式。
那么这是什么意思?
意思是说现在要做的这件事情,只是把文件拷了过来,解析这件动作和存储这件动作,还没有做。
为什么没有做?
因为要做的事情是首先是把文件放到了目录里,也就意味着原来的指定的文件不会直接对其做任何修改,不会被 Hive 做修改,它内容会被放到 database 的目录里,并没有解析内容,没有按照刚才指定的顺序去存储动作。
为什么没有按照刚才指定的顺序去存储动作?
因为与 Hive date 做的动作类似,是一种 lazy 的方式。在执行这条语句时,它知道将来数据仓库里会有文件,但是它不会去任何的处理,,一直到要去访问里面的内容时,才会去处理。原因是其默认的文件会很大,去解析存储这样的动作会花很多时间,做完之后,用户未必马上就要去访问。所以预先把开销执行掉,没有意义。因此它用了一种 lazy 的方式在执行。
刚才是配置文件里写当前的 Hive 所有的数据仓库的内目录在哪里。因为刚才创建的是 records 的表
因此它会创建叫 records 的目录。它会把刚才目录里 sample.tsc 直接拷进来放进目录。现在目录就包含了信息,未来要去读取 records 里面的内容时,它就会去解析这里的内容,拿到 sample 里的东西。按照逻辑。因此目录里头现在看起来只有文件。但是以后可以放很多个文件,甚至可以来自不同的文件格式,来自不同的地方。
4.什么时做解析的动作?
在 Hive 的命令行工具里面,要执行 hql 为查询语句。它很像 SQL 从 records 里面要去读温度,不等于9999。因为,一开始它是9999,真正的温度附进去。如果是9999,表示温度实际上没有测到。温度不等于9999,并且质量相当于这几个当中的一个。在情况下,把满足这些条件的最大的那个温度拿出来,同时把 对应的年份拿出来。
那其背后做的是什么事情?在 Hive 所在 hadoop 的集群上,把这件事情就拆分为了 MapReduce 的作业。作业一般有若干个 map 若干个 reduce 每可以去处理文件。例如刚才看到的 sample.txt 那是其中之一。每处理一个文件,最后得出结果。地方为它的输出。
1949 111
1950 22
因此当在执行动作时,真正地要去到 sample.ts 里面去抓取想要的内容。因此通过 Hive 的 shell 运行了刚才的代码,那么在运行 high Hive 之后,会看见里面有一些命令,元数据都在这里。
为它的命运行 shell 命令还有一些其它的。例如有 web 的界面的,有写 Java 的客户端的代码时,要应用依赖即在运行 Hive 把它运行为 server 。再通过 Hive server 对象运行 server 起来,去读写数据通过它去操作。实际上所有的数据最终是存在数据库里。
5.数据库里是怎么存的?
它的存储有 metastore database 为有关 touch 对它的抽象。
存整个 Hive 里面所有的数据仓库的信息,其它的数据全部都是存储在 hadoop 的集群上。那么真正的那些数据仓库的东西,通过分布式文件系统访问到它。对分布式文件系统里面存储的数据仓库在做操作时,实际上是通过之前看到的 MapReduce 那个 job client 去操作,因此它会去驱动 job client 提交 MapReduce 索引,在 hadoop 的集群上去执行整个数据仓库上的处理。所有东西都是通过所谓的 Driver 来实现。当我们起命令行的 shell 或者使用 web 界面的控制台,它其实都是把命令发送给了 Driver 去处理。
6.数据导入如何进行操作?
数据导入以后先存储再进行操作。如果是用编程方式进行操作,在用户眼里看到的是 Hive 整个就像数据源。因此它会提供类似 JDBC 的 Hive 的驱动。如果用 ODBC 就会用 ODBC 的 Driver 如果用 Thrift 就用 Thrift 客户端。这是真正写的应用。因此可以看到在我们写的应用的眼里,整个 Hive 就像数据库。它背后发生的是这样的事情。
metadata 非常重要。是相当于 Hive 里面所有元数据的集中存储的存储池。Metadata 和 metastore 里面就会提供服务,并且后面的是真正存储的数据,为存所有的数据仓库的数据,以及数据仓库的元数据。Metastore 的 service 通常和Hive service和 Driver运行在一起,这样它的性能才高,因此它们运行在虚拟机里。当然也可以分开,分开之后把它在单独的进程里去运行,那么Hive service和 Driver在单独进程里运行。例如面对比较大的操作数据仓库时,信息要单独存储,防止一边崩了所有的数据都损坏。总的来说它是在存元数据。类似在分布式文件系统里面的 name node ,假设想去操作系统的话,首先要到 Meta Storee 到里面去找所有的数据仓库的一些元数据,才能知道怎么到分布式文件系统里面去访问它。那因此我们看到它的部署会是这样的,甚至可以不只一个。
例如在集群里面比较复杂的情况下。一种是它只有它一个另一种是它和 Hive 的 Driver 在一起,或者是在集群里运行,它和 Driver 还是运行在同一个Java虚拟机里,但是它有多个实例。
更复杂的情况为这两个 Meta Storee 是两个单独的进程,和 Driver 运行在不同的进程里,这种情况下做负载均衡一般会更好,这是它运行的机制。
二、读模式与写模式
1. schema on read 与 schema on write 的差异
我们把 Hive 里面数据在加载之后,数据是不是马上就被解析存储?那按照解析存储的方式的为时间点的不同,我们还可以把它分为两种,一种称为 schema on read 一种叫 schema on write 。
两个的差异是什么?在传统的数据库里面, MySQL 这样的关系型数据库里,如果给表定义了 schema 也为那个表的结构,那表的结构是当有数据被加载进来时,也为要写入到数据,无论是通过 SQL 语句导入,还是人工一套一套往里插,在加载数据时,它就会去检查。例如主键要求不能为空,假设没有规定,除非设主键是数据库自增的或者是数据库帮我们生为的,否则它会报错。
再例如定义某字段。例如定义人的姓,字段是不能为空的。但是当在插入一条数据,当它为空时,则会报错。因此称为在数据加载了之后,它被强制约束了。因此如果数据不允不符合 schema 它就直接被拒绝且报错。就称为 schema on right 即当数据一旦加载,
就马上检查,只有符合要求的数据,才能写入到数据库里面。因此它是在写入数据库时去做这样的事情,这就叫 schema on read 。Hive 是把数据在 load 时,它只是把文件放到了目录底下。没有去解析和存储的动作,它只把文件放到了这里。Hive不做任何事情也为说明它一定不做数据 schema 的校验,它只文件放在那里。是当真正产生 query 时,
它才去做前面的动作。即当把数据导入真正执行 select 时,它才返回去做数据校验。称为读取时再做校验,这就是两者的差异。
2.schema on read 它的好处
schema on read在load时非常快,只是把文件拷过来,甚至不用拷,只需设置加载文件的引用,记住文件的位置即可。因此schema on read初始加载非常之快,它不需要做所谓的读取解析,把它再写回到硬盘,按照数据库的内部的格式写回到硬盘,因此它初始动作非常快。那么
3.schema on Redis 它的优势
schema on Redis 它的优势为一开始就校验好,再做 query 之后不需要去进行数据的校验,
因此其性能非常之好。那这是我们看到的它的。而且它在数据在加载进来之后,它额外的还可以做一些事情,例如去索引或做数据的压缩,这样做完之后它就进一步提升 query 的性能。占用的磁盘空间少了或者是索引会使查询效率变快,它会进一步地提升性能。那就看两者觉得哪更重要。
Hive 里面为什么取方式?原因是 Hive 是数据仓库,数据仓库就隐含着特点是它的数据量一定会非常大,而且它的数据的来源一般非常杂,如果一开始就去校验,那它这校验耗时会非常的多,那么它一般会花费很大的精力在这里做这件事情,而且做完之后它也不一定马上就会被用到。
于是跟这两种方式做对比时,就可以认为像 xmail 解析里面的 DOM 它是数据在解析它之前是把所有数据全拿进来,建好一棵 DOM 树放到内存里。在后面会将在这棵 DOM 树里内存的 DOM 树里去获取我们想要的。因此它的缺点是一开始建 DOM 树时会花大量时间。整个 DOM 树建好放到内存里用不用都在那里,它会占用内存。但是如果频繁的是在解析处理 xmail 会比较理想,因为后续所有操作全部都在内存里发生。
而上面就相当于是 sex 它基于事件来进行操作,文件放到这里,当要查询时就去校验,不会一开始进来对整个 xmail 的文件建一棵树。当要去获取里面的内容时,就去按流式数据一样去读 XML 文件。触发了事件之后,可以获取当时的一些信息,那它就相当于用 sex 即做数据的校验这件事情时是要花时间的。而cost 是把它平摊到以后的所有的查询里,。当遇到 Hive 就选的是前者为把它平摊到后面的 query q 里面去。而一般的关系型数据库都走的是后面途径,把它一开始做完,保证后面所有查询都比较快。
4. Hive QL 举例
SQL 和 Hive QL 做对比,可以看到它看起来很像 SQL 语句,但是它没有SQL 语句强。
Hive 在定义时需要定义数据在这张表里的存储格式。数据真正在存为文件时是存到数据库表的文件里面之后,它们是在 HDFS 上面去存储的,也就在一种分布式文件系统里存的。当然它不一定一定要强制约束或是 HDFS 也可以是其它的文件系统。既然 Hive 在 hadoop 之上, hadoop 支持底下运行在其它的文件系统之上,因此底下是什么系统它就用什么系统,而没有彻底绑定。存的元数据是存到了关系型的数据库里,就 match data 它并没有在 HDFS 里面。
同是 Hive 里面内容为啥要把它划开?
因为实际上是在一种关系型数据库里存储了整个元数据,为真正的数据仓库是在 sdfs 上存储的,因此是做了区分。道理很简单,源数据既然是所有的请求进来,都必须先去找源数据才能够对处理。当然这件事情对我们是透明的。
如图,
它实际上是提交了 Hive 的 QL QL 会被 Driver 去处理, Driver 是 Hive 的 service。它怎么处理的对我们来说是屏蔽的,它就是在通过这样的方式处理。很显然关系型数据库它的搜索效率一定会比 HDFS 高,而它是每请求进来都要访问,因此应该保证它的性能,因此它存在关系性数据库里。
可以看到它是由 Hive 来管理的,但是可以把这些表存储到数据仓库的目录里,也可以创建外部表。外部表的含义是告诉 Hive 数据它是在数据仓库之外的某目录里头存储的,要去引用它。因此这即所谓的在它目录里的这些表和外部的表。
那它两个有啥差异?
在数据仓库目录里存储的这些表是受 Hive 的管理的。有元数据管理,以及分布式文件存储等。如果要做一些相应的数据管理的操作,都在目录里的全部是被管理的。如果是在目录之外有表,那只能去访问到那个数据,数据它也许在其它的文件系统上。即对文件的管理就弱了,就超出了 Hive 的范围,它只知道我只能去读它,把它里面数据拿出来去作为数据仓库的数据源去进行处理。其它的对文件的一些在文件系统之上做的一些复杂操作已经超出了 Hive 的能力范围。但是它支持多数据源,支持异构的数据源。数据导入之后,跟关系型数据很像方面为数据量很大时,它也可以进行分区,可以指定分区。
三、Partitions and buckets 分区和桶
当加载非常大的文件时,可以看到文件拿来之后它的分区是什么。我有一系列的文件,例如 file 1 file 2 file 3 等等,
我会说 file 1 里面存储的是有关英国的天气预报,它加载进来之后是放到了表里面。但是它进来之后数据只是其中的分区之一。再给其标注一些标记,表示日期国家等。 file 2 进来时还是在 logs 表里,但是它为另外分区。那这些文件一旦被加载,从逻辑上来说,它们都在表里面,为 logs 表里面,但是它实际上是有多个分区的,那它速度就会为它的存储自然就可以分不开,它就会处理时就可以去我们说的 Mac reduce 并行地处理。
因此在一开始创建 logs 表时就会去标注清楚是分区的,
在导入文件时,可以去令导入的文件为一个分区,它的列或指定列的取值为什么,这样所有的分区就能够区分开。
在逻辑上的分法分完之后,那 file 1 如果还是很大怎么办?真正地在物理上在存储时分为称为 buckets 的。因此 partition 是逻辑上分区。这是英国的 2001 年的天气预报的数据,
但文件本身很大。例如有个 5 个 GB 那实际上存储之后如果 5 个 GB 存储是非常大的,它要分为很多小块存储。就像我们在 HDFS 里面讲的那个 block 一样,
它再分的话就称为 buckets ,那为什么我们不能把 5 GB 的文件的 partition 直接丢给 HDFS 让它直接把切开为很多小块地存储。
如果是这么做,就会有问题,很大的文件切完之后,它们存储时,它们在硬盘上的位置,在集群里位置一般就会发生变化,就它们不会连续存储。此时要注意 HDFS 怎么管理,例如会存到服务器 A 上,这是 A 上,这是 B 上,这是 B 上,这是 C 上,这是 D 上,
这件事情已经完全不受控制。一般效率会比较低。这件事情到底分为多少块,每一块在哪里完全不受控制。
但是如果人为地去把它化为在 HDFS 之上,主动在 Hive 的层面上把它化为很多小块,就有机会添加一些额外的信息进去,这些信息有助于提高搜索的效率。那例如用户表,
它有用户的 ID 和名字,把 ID 做一下聚类,按照 ID 的升序进行排序,把它们划分为四块四个 buckets 这种情况下看可以保证这四个 buckets 它们是按照 ID 的升序排序完以后去进行了划分。在进行存储时就不会出现把整个 5 GB 的空间文件拿过来后给 HDFS 区分, HDFS 在进行分割时,它可是只管文件的顺序上切。例如数据在这张表里的顺序,它本来是 ID 为 1 的人叫 Tom , ID 为 100 的人叫 jerry , ID 为 42 的人叫caocao, ID 为 101 叫liubei, ID 为 50 的人叫sunquan。
如果不靠 buckets 的区分,说我就丢给分布系统去做,那么其分的效率就非常低,未来在搜索再查找效率非常低。我们想做的事情是把它们按照 ID 升序排好之后,假如比较平均分为四块,这时拿着它们再给 HDFS 去存储时就会发现那这两块这两个在一块里,这两个在一块里,这在一块里,这在一块,为我们分四块。那看结构比刚才这边我们看到的右边结构显然效率要高一些。
这为我们要去把表划分为 buckets 的原因,为它让查询变得效率更高,
这是我们看到的,而且它使表本身它的采样也会变得更高。数据会按照这样的方式去组织存储,比原始文件拿来靠 HDFS 来帮做分布的存储,效率要高。因此这就是它划分为 buckets 的原因。