这两天在调研用 java 怎么能通过 hive metastore 将 hive 表中的数据读出来(不能用 hive2),最好是能直接支持 sql 查询。各种查跟尝试,最终确定这条路走不通。期间研究了下 hive 的内部架构,其实就是看了一遍官方文档。记录下怕忘了。
hive 中主要有两个组件 hive server2
和 hive metastore
,前者负责对外提供 DML 服务,后者记录了数据的元信息,在 sql 生成执行计划时为其提供依据。(为什么从 metastore 中查不了表中的数据,因为人家压根没存)。
hive 架构
这张图是从官网截的。里面展示了主要的组件以及它跟 hadoop(spark) 的交互。主要组件如下:
- UI:用户提交查询或者其他操作给系统的接口,2011年以后支持命令行和 web GUI 两种操作接口。
- Driver:该组件接收用户的操作请求(查询),支持来自 JDBC/ODBC 接口的请求,创建 session,执行请求并将结果返回。
- Compiler:该组件在 metastore 的协助下解析查询语句,对不同的查询块和查询语句做语法分析并产生执行计划。
- Metastore:该组件存储了数仓中全部表的结构信息和分区信息,包括列以及列类型信息。读写数据时所需的序列化和反序列化器,以及数据在HDFS上的位置信息。metastore 存储数据的元信息而非数据本身。
- Execution Engine: 该组件负责执行由 compiler 产生的执行计划(由多个stage构成的有向无环图)。它管理着执行计划中不同 stage之间的依赖关系并且在恰当的系统组件中执行 stage。
上图也展示了典型的查询操作的执行过程。通过交互接口将查询请求提交到 Driver(step 1)。Driver 为查询语句创建 session 并将其发送到 compiler 生成执行计划 (step 2)。compiler 从 metastore 中获取必要的元信息(steps 3 and 4)。compiler 生成的查询计划是由多个 stage 构成的有向无环图,并且每个 stage 都是将是一个 mapreduce 任务。Execution Engine 管理并提交这些 stage 到正确的组件(steps 6, 6.1, 6.2 and 6.3)。图中所画的 stage 被提交到 hadoop 上执行,而且是早期的 hadoop (目前已不被使用),也可以将 stage 提交到 spark 执行。每个任务执行时读取 hive 表中的数据实际上是使用该表对应的反序列化器直接从 HDFS 上读取数据,并且操作这些数据。生成的中间输出又被使用序列化器写在了 HDFS 的临时文件中供后续使用。对于 DML 操作最终的临时文件会被移动到表的位置,该方案确保了不会读到脏数据。对于查询请求,执行引擎直接从 HDFS 上读取最终文件,并将结果返回给 Driver(steps 7, 8 and 9)。
Hive 数据模型
HIve 中的数据被组织成:
- Table:HIve 表类似于关系型数据库表,filtered, projected, joined 和 union 这些功能都有,表中的数据直接存储在 HDFS 上。支持外表。
- Partitions:表中的数据可以拥有一个或多个分区,分区决定的数据在 HDFS 上如何存储,分区相同的数据存储在同一目录下。当存在多个分区时,会出现目录嵌套。通常会以时间作为分区。
- Buckets:这个概念翻译成中文叫 块、桶、有时候也叫分区,但”分区“的称呼容易和上面的概念混淆。表中同一个分区分数据会被按照某个列的 hash 值再进一步划分成块,每一块作为一个单独的文件。最终的样子是 表中相同分区的数据存储在同一目录下,该目录下有好多个文件。块的出现提高了查询的效率。
Metastore
设计初衷
Hive Metastore的设计初衷是为了解决Hive中表和分区的元数据管理问题。在Hive中,表和分区的元数据包括表名、列名、数据类型、分区键、存储位置等信息,这些元数据需要被存储和管理。Hive Metastore就是为了管理这些元数据而设计的。在没有Hive Metastore的情况下,Hive会将表和分区的元数据存储在HDFS的元数据文件中,这些文件通常被称为Hive元数据存储目录。Hive会在该目录下创建一个与表名相同的目录,并在该目录下创建一个名为“_metadata”的文件,该文件包含表的元数据信息,如表名、列名、数据类型等。对于分区,Hive会在表的元数据文件中记录分区键和分区值,但是不会记录分区的存储位置。因此,在没有Hive Metastore的情况下,用户需要手动管理分区的存储位置,这可能会导致分区管理的不便和效率低下。
具体来说,用户需要在HDFS中为每个分区创建一个目录,并将该分区的数据存储在该目录下。例如,如果有一个名为“sales”的表,其中包含一个名为“2019”的分区,用户可以按照以下步骤手动管理该分区的存储位置:
- 在HDFS中创建一个名为“sales”的目录,该目录将用于存储“sales”表的数据。
- 在“sales”目录下创建一个名为“2019”的目录,该目录将用于存储“2019”分区的数据。
- 将“2019”分区的数据存储在“sales/2019”目录下。
在手动管理分区存储位置时,需要注意以下几点:
- 分区目录的命名必须与分区键的值相同,例如,“2019”分区的目录名必须为“2019”。
- 分区目录必须位于表的存储目录下,例如,“2019”分区的目录必须位于“sales”表的存储目录下。
- 分区目录的权限必须与表的存储目录相同,以确保Hive可以访问该目录中的数据。
Metastore 如何管理元数据和分区?
- 存储表和分区元数据:Hive Metastore可以存储表和分区的元数据信息,包括表名、列名、数据类型、分区键、存储位置等。当用户创建或修改表和分区时,Hive Metastore会自动更新元数据信息。
- 支持元数据查询:Hive Metastore可以支持元数据查询,用户可以通过Hive SQL语句查询表和分区的元数据信息。Hive Metastore会自动将查询转换为对元数据存储的操作,从而实现对元数据的高效查询。
- 支持元数据修改:Hive Metastore可以支持元数据修改,用户可以通过Hive SQL语句修改表和分区的元数据信息。Hive Metastore会自动将修改转换为对元数据存储的操作,从而实现对元数据的高效修改。
- 支持元数据版本控制和事务管理:Hive Metastore可以支持元数据版本控制和事务管理,用户可以通过Hive SQL语句对元数据进行版本控制和事务管理,从而保证元数据的一致性和可靠性。
- 管理分区存储位置:Hive Metastore可以自动管理分区的存储位置,当用户创建或修改分区时,Hive Metastore会自动将分区数据存储在正确的位置。用户无需手动管理分区的存储位置,从而提高了分区管理的效率和可靠性。
- 支持分区查询:Hive Metastore可以支持分区查询,用户可以通过Hive SQL语句查询分区数据。Hive Metastore会自动将查询转换为HDFS文件系统的操作,从而实现对分区数据的高效查询。
- 支持分区权限控制:Hive Metastore可以支持分区权限控制,用户可以通过Hive SQL语句设置分区的访问权限,从而保护分区数据的安全性。
总之,Hive Metastore可以自动管理分区的存储位置和元数据信息,从而提高了分区管理的效率和可靠性。同时,Hive Metastore还支持分区查询和权限控制等功能,为用户提供了更加全面的分区管理解决方案和更搞笑的查询效率。
metadata 对象
- Database:表的命名空间。
- Table:表的 Metastore 中包含了所有列、owner、存储、序列化与反序列化信息,还可以继续包含用户指定的键值对。存储信息包括表中数据的位置信息、文件的输入输出格式、桶信息。所有的元信息在表被创建时就生成并且存储了。
- Partition:每个分区都有自己的列信息、序列化和反序列化以及存储信息。这么做是为了在不影响了老分区的前提下修改 schema。
几个小问题
1. hive metastore 比 hive server2 有什么区别?
功能不一样,hive2 对外提供数据查询功能,Metastore 管理 hive表的元数据信息,对外提供元数据信息查询功能。
2. 通过 Hive Metastore 能查询表中的数据吗?
不能。通过 Hive Metastore 本身是不能查询表中的数据的,因为 Hive Metastore 只是 Hive 的元数据存储服务,它负责管理 Hive 表的元数据信息,包括表的结构、分区信息、表的位置等,而不是存储表中的实际数据。要查询 Hive 表中的数据,需要使用 hive2 查询。在使用 Hive 查询服务时,它们会通过 Hive Metastore 获取表的元数据信息,包括表的结构、分区信息、表的位置等,然后根据这些信息从存储系统中读取表中的实际数据。因此,Hive Metastore是Hive查询服务的一个重要组件,但它本身并不能查询表中的数据。
3. 为什么 spark 可以通过 Hive Metastore 读取出表中的数据?
Spark 可以通过 Hive Metastore 读取 Hive 表中的数据,是因为 Spark SQL 和 Hive 都是基于Hadoop生态系统的,它们共享Hadoop的存储和计算资源。具体来说,Spark SQL可以通过Hive Metastore获取Hive表的元数据信息。也就是说 spark 知道它要使用的数据有哪些并且在哪里存放着,接下来 spark 任务自己就到 HDFS 上读数据了,此时不用再使用 hive2,而且整个读写与计算的过程都是在集群内,数据安全有保证。