HIVE外部表到底损失多少性能

本文通过实验对比了Hive外部表与HBase客户端在查询性能上的差异,发现除直接匹配ROWKEY外,Hive通常进行全表扫描,导致性能较慢。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们经常说HIVE外部表比内部表要慢,到底是为什么?  以HBASE为例,如果把HIVE作为一个HBASE客户端的查询工具,语句转义之后发到HBASE,HBASE返回数据,按理不至于慢很多,毕竟只多做了一层SQL到HBASE的语句的转义。 既然事实却是慢,那么我们就可以认为HIVE外部表不能这么理解,应该还有其他的东西在阻碍HIVE外部表的性能,毕竟HIVE是走MAPREDUCE。

hbase(main):003:0> count 't_device_fault_statistics'
557 row(s) in 0.2890 seconds

=> 557

这里用一个只有557条数据的HBASE表来测试,看看HIVE外部表到底和HBASE本身的客户端有哪些区别。 准别工作如下:

1. 打开HBASE UI,  http://hostname:60010/table.jsp?name=t_device_fault_statistics   这里有一个指标是requests(起初,我觉得这个是请求次数,测试之后我认为这是查询请求最后获得的行数, 因为你随便查询一个不存在的数字,你会发现这个数字是不会增长的,但是如果你查询输出10条数据,这个数字就会增长10)

2. 写一个JAVA程序,或者通过HBASE客户端也行

3. 建立HBASE的HIVE外部表

完成以上工作就开始测试,整个猜想是, 比较通过HIVE外部表访问之后requests增长和通过Hbase本身的API或者客户端访问的requests增长的区别。

当前requests: <span font-size:medium;white-space:normal;background-color:#ffffff;"="" style="word-wrap: break-word; font-family: 宋体, Arial; color: rgb(51, 51, 51);">74555

以下是程序访问,通过匹配ROWKEY的前缀,看看requests增长:

      val scan = new Scan()
      scan.setCaching(100)
      scan.setRowPrefixFilter(Bytes.toBytes("i517T5100"))

访问之后的requests为:75216,  75216-74559=657 ( 我测试很多次,表的实际行是557,但是每次这里增长657,我不确定为什么不是557,而是657)

这里暂时不管为什么不是557,而是实际的657, 总之可以看到,通过访问ROWKEY前缀,HBASE客户端只有4个requests增长,但是HIVE外部表有657。 能否这么理解,HIVE通过SQL查询是把
数据全部查询出来,然后通过HIVE本身来过滤,而HBASE查询是在服务器上过滤的,所以HIVE查询之后requests增长为表的行数. 


经过测试,除了SQL条件采用 等于 rowkey的方式,requests增长会和Hbase客户端一样,其他的一定是全表扫描。 有人说HIVE是走mapreduce,mapreduce本身也是通过scan ,也可以增加过滤来达到效果,但是实际上没有。

从上面的测试,HIVE外部表除了使用等于ROWKEY方式不慢,其他的查询应该是从HBASE加载全部数据,然后通过HIVE本身来过滤。奇怪的是等于ROWKEY方式为什么HIVE就可以通过HBASE过滤,而不是依靠HIVE自己本身呢?  说明等于ROWKEY的方式,HIVE可以直接转义成HBASE执行语句,定位一条数据,而其他方式HIVE无能为力,只能全表。
Hive 中,外部表(External Table)的设计特点是仅存储的元数据定义,而实际数据存储在外部存储系统中(如 HDFS)。因此,直接删除外部表的数据不会像管理内部(Managed Table)那样自动清除底层数据[^1]。 要删除 Hive 外部表中的数据,需采取以下方法之一或组合使用: ### 删除外部表的元数据 如果仅需要移除的定义,而不删除底层数据,可以使用 `DROP TABLE` 语句: ```sql DROP TABLE IF EXISTS external_table_name; ``` 此操作仅删除 Hive 中的定义,原始数据仍然保留在其存储位置[^1]。 ### 手动删除底层数据 由于外部表的数据不由 Hive 管理,因此需要手动从存储系统中删除数据。例如,如果数据存储在 HDFS 上,可以使用以下命令: ```bash hadoop fs -rm -r /path/to/external/table/data ``` ### 清空外部表数据(保留元数据) 若希望清空外部表的数据但仍保留其定义,可以采用以下方法: 1. **重命名外部表并重建**: - 首先重命名原: ```sql ALTER TABLE external_table_name RENAME TO external_table_name_old; ``` - 然后创建一个空的外部表: ```sql CREATE EXTERNAL TABLE external_table_name ( column1 STRING, column2 INT ) LOCATION '/path/to/new/data/location/'; ``` 2. **使用分区**(如果适用): - 如果外部表是分区,可以删除特定分区数据: ```sql ALTER TABLE external_table_name DROP IF EXISTS PARTITION (partition_column='value'); ``` - 此操作会删除对应的元数据,但底层 HDFS 数据仍需手动清理[^1]。 ### 使用 Hive ACID 事务(需启用事务支持) 如果 Hive 环境支持 ACID 事务(Hive 0.14+),可以将外部表设置为事务,并使用 `DELETE` 语句: ```sql DELETE FROM TABLE external_table_name WHERE condition; ``` 此方法要求 Hive 文件格式支持事务性操作,并且底层存储系统需兼容 ACID 语义。 ##
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tom_fans

谢谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值