Hive是由Facebook开源,基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。
Hive是一个基于Hadoop的数据仓库工具,可以将结构化数据文件映射为一张表,同时可以将H-SQL语句转化为MapReduce程序在集群上运行。
客户端 ->Hive/HiveServer2->MetaStore->Hadoop->MapReduce
1.首先客户端访问Hive或者访问HiveServer2
2.其次MetaStore通过访问Hadoop来记录相关元数据
3.前两步是启动Hive连接之后的预备操作,
现在就可以看到数据了,通过写SQL语句来操作数据
4. Driver驱动器 通过生成计划找到最优解来调用YARN
这时候访问元数据 HADOOP YARN
Hive大致由hive服务模块、hive客户端模块、以及元数据存储模块和真实数据数据存储模块所组成。通常通过hive命令启动hive客户端需要启动metastore服务来保证对元数据的访问,而元数据是保存在第三方的关系型数据库中,例如MySQL。如果想使用第三方客户端工具远程访问Hive数据,我们要启动hiveserver2服务。接下来如果执行一条查询语句,首先由客户端发起请求hive,然后hive会通过自身的Driver引擎对查询语句进行语义分析生成逻辑执行计划,然后在对其进行优化,然后再将其转化成MR程序,就是所谓的物理执行计划,最后在对MR物理执行计划进行优化,最后再将MR程序默认提交Yarn集群执行,在这个过程中会通过对元数据的访问操作达到和Hadoop集群的交互。最终查询结果会返回给客户端窗口。
内部表:在Hive中删除元数据时将HDFS的数据一并删除
外部表:删除元数据时不删除HDFS的数据
内部表:储存修改的临时数据 如:原始日志修改后的数据表
外部表:储存最原始数据 比如原始日志
在 Hive 中,我们可以创建两种类型的表:内部表(Managed Table)和外部表(External Table)。
当我们创建内部表时,Hive 会完全管理表的数据和元数据。也就是说,数据的生命周期由 Hive 来控制。当我们删除内部表时,Hive 会同时删除元数据和存储在 HDFS 上的数据。这种表适合用于临时数据和中间结果的存储。
当我们创建外部表时,Hive 只管理元数据,而数据的生命周期需要用户自己来控制。当我们删除外部表时,Hive 只删除元数据,而数据仍然保留在 HDFS 中。这种表适合用于共享数据和持久化数据的存储。如果你有多个 Hive 实例或者其他应用需要访问同一份数据,那么使用外部表会很有帮助。
选择内部表还是外部表主要取决于数据的使用场景和生命周期。如果你的数据是临时的、只被 Hive 使用,那么可以选择内部表;如果你的数据是持久的、需要被多个应用或者 Hive 实例共享,那么应该选择外部表
HiveServer2 提供远程访问服务
客户通过访问HiveServer2这个中间件来访问Hadoop集群
HiveServer2通过开启用户模拟功能来实现HiveServer2的访问用户与Hadoop的访问用户达到一致,从而提高安全性(权限隔离)。
为Hive和HiveServer2提供元数据访问接口
分为两种
嵌入式:Hive内置,只能为Hive和HiveServer2提供服务,
独立服务: 通过访问独立的MetaStore来访问元数据库,数据都存在这个Metastore中
在 Hive 的架构中,HiveServer2 和 Metastore 是两个非常重要的组件。它们分别负责处理客户端的查询请求和存储 Hive 的元数据。
HiveServer2 是 Hive 提供的服务接口,用户可以通过它向 Hive 提交 HQL 查询和其他命令。HiveServer2 支持多用户并发和认证,起到动态代理登录用户及模拟用户的功能。它还提供了 JDBC 和 ODBC 的接口,允许外部应用程序连接到 Hive。例如,你可以通过 HiveServer2 从 Python、Java、 C++等应用程序或者一些可视化工具中查询 Hive 的数据。
Metastore 是 Hive 访问元数据的服务,Hive 的元数据包括表的名字、列的名字和类型、表的分区、表的存储位置等等信息。Hive 的所有操作,例如创建表、查询表、修改表,都需要通过 Metastore 来获取或者更新元数据。Metastore 可以被部署在同一个 HiveServer2 进程中,也可以被部署为一个独立的服务,供多个 Hive 实例共享。
总的来说,这两个服务都是 Hive 架构的重要组成部分,确保了 Hive 的功能和性能。HiveServer2 为用户提供了访问 Hive 的接口,而 Metastore 则为 Hive 提供了元数据管理的功能。
1.order by 全局排序 大表不拆分进行排序
2.sort by 局部排序,区内进行排序
3.distribute 这个排序是其实不算排序,是一个map的分区规则,按照hash对区数取余分区
在 Hive 中,我们主要可以使用三种方式进行排序:order by,sort by 和 distribute by。这三种方式在排序结果和性能上有所不同。
order by这是最简单的排序方式,它会对输入的所有数据进行全局排序。order by 在执行时会生成一个单独的 Reducer 来进行排序,这意味着所有的数据都需要发送到这个 Reducer 上,然后在 Reducer 上进行排序。这个过程会消耗大量的时间和计算资源,所以 ORDER BY 适合小数据集的排序,但是对于大数据集的排序,性能可能会比较差。
sort by 会在每个 Reducer 上分别对数据进行排序,然后按照 Reducer 的顺序输出结果。因为 sort by 可以并行地在多个 Reducer 上进行排序,所以它比 order by 的性能更好。但是,sort by不能保证全局排序的结果,只能保证在每个 Reducer 输出的文件内部是有序的,并且sort by 执行过程中进入每一个Reducer的数据是随机的。
distribute by 并不直接进行排序,而是决定 MapReduce 任务中的数据分发。distribute by 会根据指定的列将数据分发到不同的 Reducer 上,保证相同的键值会被分发到同一个 Reducer。通常,我们会和 sort by 一起使用 distribute by,以达到更好的排序效果。
1.创建分区表: 通过partition by 关键字结合相关的分区字段来创建分区表
2.分区表的好处:
首先先明确一下分区表什么。分区表将一个表按某个字段进行划分,这里和MapReduce的分区其实并没有什么区别。将一整块大数据分成了许许多多的小数据。
查询和修改都变的方便了,可以按照分区字段直接定位。
Hive 中的分区表实质上就是在HDFS中将表的数据进行分目录管理,从而达到提升查询效率的目的。分区表在建表的时候就要去指定,通过partitioned by 关键字结合分区字段来创建分区表。分区表可以声明多级分区表。
分区表的主要好处在于大概有三个方面,提高查询效率、降低存储成本、方便数据管等。
当你在查询数据时,如果你的查询条件包含了分区列,那么 Hive 只需要读取满足条件的分区的数据,而不需要读取整个表的数据。这样可以大大提高查询效率。
你可以为不同的分区设置不同的存储格式和压缩算法,以降低存储成本。例如,对于历史数据,你可以选择更高的压缩比例,以节省存储空间。
分区还可以让你更方便地管理数据。例如,你可以单独删除或者归档某个分区的数据,而不影响其他分区。
虽然分区表的优点很明显,但是过度分区可能会导致元数据的管理成本增加,影响查询性能。因此,设计分区时应该考虑到表的大小、查询模式和数据的生命周期等因素。
这里要区分一下,分区表有两种,一种是静态分区,一种是动态分区。
在 Hive 中,加载数据及创建分区主要有两种场景,分别是静态分区和动态分区
针对静态分区加载数据场景,使用load或者insert都可以,但是需要注意的是在加载数据的同时要对分区字段也要赋值,对分区字段赋值其实也是创建分区的过程。这个过程需要手动赋值进行操作。
针对动态分区加载数据场景,可以依赖特定的查询结果往分区表中插入数据及自动的创建分区。需要注意的是这种场景要求分区字段必须来源被查询的表中,以及整个分区表中的数据也是来自于被查询的表。
在使用 Hive 分区表时,有几个重要的注意事项:
分区数量:虽然更多的分区可以提高查询效率,但是过度分区可能会导致元数据的管理成本增加,影响查询性能。Hive 的元数据存储在元数据存储中,如果分区数量过多,可能会使得元数据存储过载,造成性能瓶颈。一般来说,一个表的分区数量最好不要超过几万个。
数据倾斜:如果分区键的选择不合理,可能会导致数据倾斜,即一部分分区的数据量远大于其他分区。数据倾斜会严重影响查询性能和资源利用率。因此,你应该选择一个可以均匀分布数据的键作为分区键。
分区维护:随着时间的推移,可能会有新的分区加入,也可能会有旧的分区被删除。你需要确保有足够的资源和策略来管理这些分区,例如,定期归档或者删除旧的分区,以释放存储空间。
总的来说,分区是一种强大的工具,可以大大提高查询效率和数据管理的便利性。但是,你也需要小心地选择分区键和数量,以避免数据倾斜和过度分区的问题。同时,你也需要有足够的资源和策略来管理和维护分区。
在 Hive 中,你可以创建被“桶”划分的表,我们称之为分桶表。与分区表类似,分桶表是另一种细粒度的数据分隔策略。桶的数目在创建表时定义,并且不会随着数据的增加而改变。
创建分桶表的语法如下:
CREATE TABLE table_name (column1 type1, column2 type2,…)
CLUSTERED BY (column_name) INTO num_buckets BUCKETS;
例如,如果你有一个订单表,你可以根据订单 id 进行分桶,创建语句如下:
CREATE TABLE orders (order_id INT, product_id INT, price FLOAT)
CLUSTERED BY (order_id) INTO 64 BUCKETS;
在这个例子中,所有的订单根据 order_id 列的值被划分到 64 个桶中。每个桶都对应一个 HDFS 文件,具有相同 order_id 值的订单会被放入同一个桶。
那么在什么情况下会使用分桶表呢?
数据倾斜问题:在大数据处理中,数据倾斜是一个常见的问题,数据倾斜意味着某些键值的数据量远大于其他键值,这会导致资源利用不均。通过分桶,我们可以将数据更均匀地分布到不同的桶中,从而减轻数据倾斜的问题。
优化特定类型的查询:例如,对于 join 操作,如果两个表都按照 join 列进行了分桶,并且桶的数量相同,那么 Hive 可以在每个桶上单独进行 join,从而并行处理多个桶,提高查询效率。
采样查询:Hive 提供了一种基于桶的采样机制,可以只读取一个或者多个桶的数据。这对于在大数据集上进行快速探索或者调试非常有用。
但是需要注意的是,分桶需要更精细的设计和管理,不适合所有情况。并且,分桶不能替代分区,分区和分桶在数据管理和查询优化方面有各自的优点,通常会一起使用。
分桶能控制的只有桶的个数和按照的列,而分配规则由Map决定
分区则更细化,不规定个数。
分桶的桶Join支持大表的MapJoin而分区不行
round
rand
ceil floor
substring
current_date
date
datediff date_add
行转列: collect_Set/collect_list
列转行: explode炸裂
行转列:在 Hive 中,行转列通常使用聚合函数,例如 collect_set 或 collect_list。这些函数可以将特定列的多个行值聚合成一个集合或列表。例如,如果有一个包含用户 ID 和他们购买的商品的表,你可以使用如下查询将每个用户购买的所有商品聚合到一个列表中:
SELECT user_id, collect_list(product) as product_list FROM purchasesGROUP BY user_id;
这将生成一个新的表,其中每一行对应一个用户 ID,产品列则包含该用户购买的所有产品的列表,这样就实现了从行到列的转换。
列转行:在 Hive 中,列转行通常使用 explode 函数。当你有一列是数组或 map 类型的数据,你可以使用 explode 函数将其展开为多行。例如,如果有一个表包含用户 ID 和他们购买的商品列表,你可以使用如下查询将商品列表展开为多行:
SELECT user_id, explode(product_list) as productFROM purchases;
这将为每个用户和每个商品生成一行,也就是将商品列表展开为多行,实现了从列到行的转换。但是如果列转行后想要和原表中的数据进行对应的话需要结合lateral view进行侧写来完成。
观察开窗,首先看一下聚合函数group by的区别
聚合函数:group by通过修改表结构来改变表的内容
开窗函数:通过partition by orderby等,不需要修改表结构从而对特定窗口内的数据进行计算.或者说开窗是加强版的聚合。
在原表的操作上直接进行聚合操作,同时并不修改表结构,并且每一行都能得到一个结果,从而得到聚合后的结果。
开窗函数(Window Functions)是 SQL 的一部分,用于处理比普通的聚合查询更复杂的数据分析任务。开窗函数在进行计算时,会为输入的每一行定义一个"窗口",这个窗口内的行集合是这一行的函数计算的基础。
一个窗口函数的执行可以分为三个步骤:
分区:首先,所有的行会根据 PARTITION BY 子句进行分区,具有相同 PARTITION BY 表达式值的行属于同一分区。
排序:然后,每个分区中的行会根据 ORDER BY 子句进行排序。
窗口定义:最后,对于每一行,都会在其所在分区内定义一个窗口。这个窗口由 ROWS 或 RANGE 子句定义,这个窗口内的行就是该行的窗口函数计算的基础。
窗口函数的强大之处在于,尽管它们进行的是聚合操作(比如求和、计数、找最大/最小值等),但它们并不像普通的聚合函数那样将多行聚合成一行,而是为输入的每一行都返回一个结果。这样,就可以在保留详细信息的同时进行聚合分析。
例如,你可以使用窗口函数来计算每个用户的购买总额,并与其他用户的购买总额进行比较,以此来找出购买最多的用户。在这个例子中,每一行(即每一个用户)的窗口是由该用户的所有购买组成的,窗口函数是求和函数,用来计算窗口内的购买总额。
总的来说,开窗函数的本质是通过为每一行定义一个"窗口"(也就是一组相关联的行),然后对这个窗口进行聚合计算,为每一行返回一个结果,以此来进行更复杂的数据分析。