草庐IT

Hive 事务表 (Transactional Tables)

ElegantCodingWH 2024-06-12 原文

文章目录

1. 为什么要使用事务表?

  • Hive 原本是不支持事务的,也就是不支持 增删改(insert、delete、update)、回滚等 操作的。因为:
    1. Hive的核心目标是: 将已经存在的结构化数据文件映射成为表,然后提供基于表的SQL分析处理。也就是说Hive是面向分析的,并不是面向设计的。
    2. HDFS不支持随机修改文件。
  • 但是随着技术的发展,不支持事务在某些方面也会带来很大的弊端,如:
  • 所以Hive0.14后开始支持事务,即创建事务表。但是事务表有很大的限制:

2. 创建使用事务表

  • 第一步:开启事务配置(可以使用set设置当前session生效 也可以配置在hive-site.xml中)

    set hive.support.concurrency = true; --Hive是否支持并发
    set hive.enforce.bucketing = true; --从Hive2.0开始不再需要 是否开启分桶功能
    set hive.exec.dynamic.partition.mode = nonstrict; --动态分区模式 非严格
    set hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; --
    set hive.compactor.initiator.on = true; --是否在Metastore实例上运行启动线程和清理线程
    set hive.compactor.worker.threads = 1; --在此metastore实例上运行多少个压缩程序工作线程
    
  • 第二步:在创建表时加上① clustered by关键字;② stored as关键字;③ TBLPROPERTIES('transactional'='true')关键字

    create table trans_student(
    id int,
    name String,
    age int
    )
    -- 1. 必须为分桶表(如果在前面通过set开启了分桶功能,那么这里可以不写该语句)
    clustered by (id) into 2 buckets
    -- 2. 存储方式为 orc 
    stored as orc 
    -- 3. 设置表属性transactional为true,开启事务
    TBLPROPERTIES('transactional'='true');
    
  • 然后就可以使用 insert、update、delete 对事务表进行事务操作。

    注意:使用insert update delete操作数据时,并不是真正的插入/修改/删除数据,而是重新创建了一个新文件,将数据写入进去,并将原文件做了删除标记。通过标记的方式来实现事务。(后面会介绍)

3. 实现原理

3.1 事务产生文件夹

由于HDFS中只支持追加数据,并不能像MySQL一样随机修改数据。所以,采用不改变原始数据,创建文件进行标记的方法来实现事务:

  1. 每次执行一次事务操作都会创建一个文件夹:

    1. insert语句会创建delta_xxx_xxx_xxx文件夹;
    2. delete语句会创建delete_delta_xxx_xxx_xxx文件夹;
    3. update语句是通过delete、insert两个语句完成的,即先删除,后添加。

    关于_xxx是怎么命名的?

    1. Hive会为每个写入语句(INSERT、DELETE等)创建一个写事务ID(Write ID),该ID是自增的;
    2. 而一个事务可能含有多条写入语句时,即会产生多个写事务ID。因为ID是自增的,所以,一个事务内的多个写事务ID是连续,故可用mixWID 至 maxWID表示此次事务的所有写事务ID,然后再用stmtID对写事务ID进行区分。
    3. 因此,命名规范为delta_minWID_maxWID_stmtID
  2. 正在执行中的事务,是以一个.hive-staging_hive_xxx的文件夹维护的,执行结束后就会改名为delta_xxx_xxx_xxxdelete_delta_xxx_xxx_xxx文件夹。

  3. 当访问Hive数据时,根据HDFS原始文件和相应的delta增量文件做合并,从而得到查询数据。

3.2 那么文件夹里面有什么?

每个事务的delta文件夹下,都有两个文件:

  1. orc_acid_version文件:文件里的内容是2,标识acid版本为2。和版本1的主要区别是UPDATE语句采用了split-update特性,即先删除、后插入。

  2. bucket_00000文件:文件里是写入的数据内容。如果事务表没有分区和分桶,就只有一个这样的文件。

    由于是orc格式存储,底层用二级制存储,因此直接打开文件看不懂,需要使用ORC TOOLS查看。

3.3 合并器(Compactor)

  1. 随着表的修改操作越多,delta增量文件会越来越多,就需要定时将文件合并以保持足够的性能。
  2. 合并器Compactor是一套在Hive Metastore内运行,支持ACID系统的后台进程。所有合并都是在后台完成的,不会阻止数据的并发读、写。合并后,系统将等待所有旧文件的读操作完成后,删除旧文件。
  3. 合并操作分为两种:
    1. minor compaction(小合并):将一组delta增量文件重写为单个增量文件,默认触发条件为10个delta文件;
    2. major compaction(大合并):将多个增量文件基础文件重写为新的基础文件,默认触发条件为delta文件相应于基础文件占比,10%。

有关Hive 事务表 (Transactional Tables)的更多相关文章

  1. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  2. ruby - 分布式事务和队列,ruby,erlang,scala - 2

    我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和

  3. Hive SQL 五大经典面试题 - 2

    目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类

  4. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  5. ruby-on-rails - 在 rails 中提交后回滚事务 - 2

    保存成功后可以回滚吗?让我有一个带有属性名称、电子邮件等的用户模型。例如u=User.newu.name="test_name"u.email="test@email.com"u.save现在记录将成功保存在数据库中,之后我想回滚我的事务(不是销毁或删除)。有什么想法吗? 最佳答案 您可以通过交易来做到这一点,请参阅http://markdaggett.com/blog/2011/12/01/transactions-in-rails/例子:User.transactiondoUser.create(:username=>'Nemu

  6. ruby - 如何使用 PG Ruby Gem 有条件地回滚事务 - 2

    我目前正在上一门数据库类(class),其中一个实验室问题让我困惑于如何实现上述内容,事实上,如果可能的话。我试过搜索docs但是定义的交易方式比较模糊。这是我第一次尝试在没有Rails的情况下进行任何数据库操作,所以我有点迷茫。我已经成功地创建了一个到我的postgresql数据库的连接并且可以执行语句,我需要做的最后一件事是根据一个简单的条件回滚一个事务。请允许我向您展示代码:require'pg'@conn=PG::Connection.open(:dbname=>'db_15_11_labs')@conn.prepare('insert','INSERTINTOhouse(ho

  7. ruby-on-rails - 在 Rails 的一个 ActiveRecord 事务中更新多条记录 - 2

    如何使用Rails中的事务block一次性更新/保存模型的多个实例?我想更新数百条记录的值;每条记录的值都不同。这不是一个属性的批量更新情况。Model.update_all(attr:value)在这里不合适。MyModel.transactiondothings_to_update.eachdo|thing|thing.score=rand(100)+rand(100)thing.saveendendsave似乎发布了它自己的事务,而不是将更新分批处理到周围的事务中。我希望所有更新都在一次大交易中进行。我怎样才能做到这一点? 最佳答案

  8. ruby-on-rails - Rails Controller 操作是否隐式定义事务绑定(bind)? - 2

    给定以下代码:defcreate@something=Something.new(params[:something])thing=@something.thing#anothermodel#modificationofattributesonboth'something'and'thing'omitted#doIneedtowrapitinsideatransactionblock?@something.savething.saveendcreate方法是隐式包装在ActiveRecord事务中,还是需要将其包装到事务block中?如果我确实需要包装它,这是最好的方法吗?

  9. 大数据之Hadoop数据仓库Hive - 2

    目录:一、简介二、HQL的执行流程三、索引四、索引案例五、Hive常用DDL操作六、Hive常用DML操作七、查询结果插入到表八、更新和删除操作九、查询结果写出到文件系统十、HiveCLI和Beeline命令行的基本使用十一、Hive配置一、简介Hive是一个构建在Hadoop之上的数据仓库,它可以将结构化的数据文件映射成表,并提供类SQL查询功能,用于查询的SQL语句会被转化为MapReduce作业,然后提交到Hadoop上运行。特点:简单、容易上手(提供了类似sql的查询语言hql),使得精通sql但是不了解Java编程的人也能很好地进行大数据分析;灵活性高,可以自定义用户函数(UDF)和

  10. ruby-on-rails - TimeOut 与事务 block rails - 2

    据我了解,如果我们在此交易中有任何代码,并且当它发生任何错误时(保存!,...)在该block中,整个代码将恢复,这里的问题是是否有任何超时(racktimeout=12)发生在这个block中。defcreateActiveRecord::Base.transactiondo//timeouthappensendend当Rack::Timeout发生时,我们如何使用事务回滚代码? 最佳答案 当发生Rack超时时,任何正在进行的事务都将被回滚,但是已经提交的事务当然会保持提交状态。您不必为此担心。一旦启动数据库事务,它最终将被提交或

随机推荐