暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Hive 3的ACID表

大数据杂货铺 2020-03-02
594
您可以创建ACID(原子性,一致性,隔离性和持久性)表用于不受限制的事务或仅插入的事务。这些表是Hive托管表。数据与Schema一起位于Hive metastore中。或者,您可以创建一个外部表用于非事务性使用。数据位于Hive Metastore外部。模式元数据位于Hive Metastore内部。因为外部表受Hive的控制很弱,所以该表不符合ACID。

下图描述了Hive表的类型。

以下矩阵包括可以使用Hive创建的表的类型、是否支持ACID属性、所需的存储格式以及关键的SQL操作。

表类型

ACID特性

文件格式

插入

更新/删除

托管表:CRUD事务

ORC

托管表:仅插入式事务

任意格式

没有

托管表:临时

没有

任意格式

没有

外部表

没有

任意格式

没有

虽然不能使用SQL UPDATE或DELETE语句删除某些类型的表中的数据,但是可以对任何类型的表使用DROP PARTITION来删除数据。

表存储格式
CRUD表中的数据必须为ORC格式。实现支持AcidInputFormat和AcidOutputFormat的存储处理程序等效于指定ORC存储。

仅插入使用的表支持所有文件格式。

默认情况下,托管表的存储类型为“优化行列”(ORC)。如果在表创建的过程中未指定任何存储来接受默认的设置,或者指定了ORC存储,则将获得具有插入、更新和删除(CRUD)功能的ACID表。如果指定其他任何存储类型,例如text、CSV、AVRO或JSON,则将获得仅插入的ACID表。您不能更新或删除仅插入表中的列。

事务表
事务表是驻留在Hive仓库中的ACID表。为了实现ACID合规性,Hive必须管理表,包括访问表数据。只有通过Hive才能访问和更改托管表中的数据。由于Hive可以完全控制托管表,因此Hive可以广泛地优化这些表。

与用作联机分析处理(OLAP)系统相反,Hive旨在支持相对较低的事务率。您可以使用SHOW TRANSACTIONS命令列出未完成和中止的事务。

Hive 3中的事务表与非ACID表相当。Hive 3事务表中不需要桶或排序。桶化不会影响性能。这些表与原生云存储兼容。

Hive支持一个事务一个语句,该语句可以包含任意数量的行、分区或表。

外部表
外部表数据不是Hive拥有或控制的。当您想使用Hive以外的其他工具直接在文件级别访问数据时,通常使用外部表。您还可以使用存储处理程序(例如Druid或HBase)来创建位于Hive元存储之外的表。

Hive 3不支持以下外部表功能:

查询缓存
物化视图,但以受限的方式除外
默认的统计信息收集
使用统计信息计算查询
自动运行时过滤
插入后合并文件

在外部表上运行DROP TABLE时,默认情况下,Hive仅删除元数据(Schema)。如果您希望DROP TABLE命令也删除外部表中的实际数据,就像DROP TABLE在托管表上所做的那样,则需要将external.table.purge属性设置 为true。

表的位置

在Cloudera数据平台(CDP)公共云中,您可以在设置数据仓库期间指定托管表和外部表元数据在Hive仓库中的位置。例如:

    hive.metastore.warehouse.external.dir = s3a://bucketName/warehouse/tablespace/external/hive
    hive.metastore.warehouse.dir=s3a://bucketName/warehouse/tablespace/managed/hive

    在Cloudera Manager(CM)中,当您启动集群时,您接受默认值或指定Hive Metastore变量,hive.metastore.warehouse.dir和 hive.metastore.warehouse.external.dir确定Hive表的存储位置。托管表位于托管表空间中,只有Hive可以访问。默认情况下,Hive假定外部表位于外部表空间中。

    要确定托管表或外部表的类型,可以运行DESCRIBE EXTENDED table_name命令。

    安全性和Spark访问

    下表和后续各节介绍了托管(事务)表与外部表之间的其他区别:

    表类型

    安全

    Spark访问

    最佳化

    托管表(事务)

    仅支持Ranger授权,无简单身份验证

    是的,使用Hive Warehouse Connector

    统计及其他

    外部表

    Ranger或简单身份验证

    是的,直接文件访问

    有限

    创建CRUD事务表
    当需要可更新、删除和合并的托管表时,可以创建具有ACID(原子性,一致性,隔离性和持久性)属性的CRUD事务表。默认情况下,表数据以优化行列(ORC)文件格式存储。

    创建仅插入的事务表
    如果不需要更新和删除功能,则可以使用任何存储格式创建事务表。这种类型的表具有ACID属性,是托管表,并且仅接受插入操作。仅插入表的存储格式不限于ORC。

    创建,使用和删除外部表
    您可以使用外部表(该表是Hive不能管理的表)将数据从文件系统上的文件导入Hive。与Hive托管表相反,外部表将其数据保留在Hive元存储之外。Hive Metastore仅存储外部表的架构元数据。Hive不管理或限制对实际外部数据的访问。

    删除外部表和数据
    外部表上 运行DROP TABLE时,默认情况下,Hive仅删除元数据(模式)。如果您希望DROP TABLE命令也删除外部表中的实际数据,就像DROP TABLE在托管表上一样,则需要相应地配置表属性。

    使用约束
    您可以在Hive ACID表定义中使用DEFAULT,PRIMARY KEY,FOREIGN KEY和NOT NULL约束来提高数据的性能、准确性和可靠性。

    确定表类型
    您可以确定Hive表的类型,它是否具有ACID属性,存储格式(例如ORC)和其他信息。出于多种原因,了解表类型非常重要,例如了解如何在表中存储数据或从集群中完全删除数据。

    使用约束
    您可以在Hive ACID表定义中使用DEFAULT,PRIMARY KEY,FOREIGN KEY和NOT NULL约束来提高数据的性能,准确性和可靠性。

    如果数据可预测且易于定位,则Hive引擎和BI工具可以简化查询。Hive强制执行以下约束:

    • 默认

      • 确保存在一个值,该值在数据仓库卸载案例中很有用。

    • 主键

      • 使用唯一标识符标识表中的每一行。

    • 外键

      • 使用唯一标识符标识另一个表中的行。

    • 非空

      • 检查列值未设置为NULL。

    优化器使用该信息做出明智的决策。例如,如果引擎知道某个值是主键,则它不会查找重复项。以下示例显示了约束的使用:

      CREATE TABLE Persons (  
      ID INT NOT NULL,
      Name STRING NOT NULL,
      Age INT,
      Creator STRING DEFAULT CURRENT_USER(),
      CreateDate DATE DEFAULT CURRENT_DATE(),
      PRIMARY KEY (ID) DISABLE NOVALIDATE);


      CREATE TABLE BusinessUnit (
      ID INT NOT NULL,
      Head INT NOT NULL,
      Creator STRING DEFAULT CURRENT_USER(),
      CreateDate DATE DEFAULT CURRENT_DATE(),
      PRIMARY KEY (ID) DISABLE NOVALIDATE,
      CONSTRAINT fk FOREIGN KEY (Head) REFERENCES Persons(ID) DISABLE NOVALIDATE
      );
      确定表类型
      您可以确定Hive表的类型,是否具有ACID属性,存储格式(例如ORC)和其他信息。出于多种原因,了解表类型非常重要,例如,了解如何在表中存储数据或从集群中完全删除数据。

      1. 在Hive Shell中,获取对该表的扩展描述。

      例如: DESCRIBE EXTENDED mydatabase.mytable;

      2. 滚动到命令输出的底部以查看表类型。

      以下输出包括对表类型的管理,并 transaction=true指示该表具有ACID属性:


        ...
        | Detailed Table Information | Table(tableName:t2, dbName:mydatabase, owner:hdfs, createTime:1538152187, lastAccessTime:0, retention:0, sd:StorageDescriptor(cols:[FieldSchema(name:a, type:int, comment:null), FieldSchema(name:b, type:int, comment:null)], ...
        HMS表存储
        您需要了解在运行CREATE TABLE语句或将表迁移到Cloudera Data Platform时HMS如何存储Hive表。语句的成功或失败,结果表类型和表位置取决于许多因素。
        HMS表转换
        HMS包含以下有关您创建的表的Hive元数据:

        表定义

        列名

        资料类型

        中央模式存储库中的注释

        在CREATE TABLE语句中使用EXTERNAL关键字时,HMS将表存储为外部表。当您省略EXTERNAL关键字并创建托管表或读取托管表时,HMS可能会将表转换为外部表,否则表创建可能失败,具体取决于表属性。影响表转换的重要表属性是ACID或Non-ACID表类型:
        • 非ACID

          • 如果表属性不包含任何与ACID相关的属性,则此属性为true 。例如,该表不包含此类属性 transactional=trueinsert_only=true

        • ACID

          • 如果表属性确实包含一个或多个ACID属性,则此属性为true。

        • 完全的ACID

          • 此属性为true,如果表属性包含 transactional=true但不是 insert_only=true

        • 仅插入的ACID

          • 表属性包含insert_only=true

        以下矩阵显示了表类型以及是否支持location属性。
        ACID

        位置属性

        注释

        行动

        注释

        Non-ACID

        迁移到CDP,例如从HDP或CDH群集

        表存储为外部

        非ACID,ACID,完整ACID,仅插入ACID

        没有

        表位置为空

        表存储在子目录中 metastore.warehouse.external.dir

        HMS检测用于与HMS进行交互的客户端类型,例如Hive或Spark,并将客户端的功能与表要求进行比较。HMS根据比较结果执行以下操作:

        表要求

        客户端符合要求

        托管表

        ACID表类型

        结果

        行动

        客户端可以写入任何类型的ACID表

        没有

        创建表失败


        客户端可以写入完整的ACID表

        没有

        insert_only = true

        创建表失败


        客户端可以写入仅插入的ACID表

        没有

        insert_only = true

        创建表失败


        例如,如果Spark客户端不具备所需的功能,则会出现以下类型的错误消息:
          Spark has no access to table `mytable`. Clients can access this table only if
          they have the following capabilities: CONNECTORREAD,HIVEFULLACIDREAD, HIVEFULLACIDWRITE,
          HIVEMANAGESTATS, HIVECACHEINVALIDATE, ...
          Hive 3 ACID事务
          Hive 3实现对事务表的原子性和隔离性操作是通过使用涉及增量文件的写入、读取、插入、创建、删除和更新操作的技术来实现,这些技术可以提供查询状态信息并帮助您解决查询问题。

          读写操作

          Hive 3的读写操作提高了事务表的ACID的质量和性能。事务表的性能与其他表一样。Hive支持所有TPC Benchmark DS(TPC-DS)查询。
          Hive 3和更高版本将原子操作从简单的写入和插入扩展为支持以下操作:

          写入多个分区

          在单个SELECT语句中使用多个insert子句

          一条语句可以写入多个分区或多个表。如果操作失败,则用户看不到部分写入或插入。即使数据经常更改,例如每小时更改百分之一,操作仍然保持快速。Hive 3和更高版本不会覆盖整个分区以执行更新或删除操作。
          Hive自动压缩ACID事务文件,而不会影响并发查询。当查询许多小的分区文件时,自动压缩可提高查询性能和元数据占用量。
          读取语义包括快照隔离。当读取操作开始时,Hive在逻辑上锁定仓库的状态。读操作不受操作期间发生的更改的影响。

          仅插入表中的原子性和隔离性

          当仅插入事务开始时,事务管理器将获得事务ID。对于每次写入,事务管理器都会分配一个写入ID。此ID确定实际写入数据的路径。以下代码显示创建仅插入事务表的语句示例:

            CREATE TABLE tm (a int, b int) TBLPROPERTIES
            ('transactional'='true', 'transactional_properties'='insert_only')
            假设发生了三个插入操作,而第二个失败:

              INSERT INTO tm VALUES(1,1);
              INSERT INTO tm VALUES(2,2); Fails
              INSERT INTO tm VALUES(3,3);
              对于每个写入操作,Hive都会创建一个增量目录,事务管理器将在该目录中写入数据文件。Hive将所有数据写入由写入ID指定的增量文件,并映射到表示原子操作的事务ID。如果发生故障,该事务将标记为已中止,但它是原子的:

                tm
                ___ delta_0000001_0000001_0000
                └── 000000_0
                ___ delta_0000002_0000002_0000 //Fails
                └── 000000_0
                ___ delta_0000003_0000003_0000
                └── 000000_0
                在读取过程中,事务管理器维护每个事务的状态。当读取器启动时,它会请求快照信息,该信息由高水印表示。水印标识系统中最高的事务ID,后跟代表仍在运行或中止的事务的异常列表。
                读取器查看增量,并过滤出或跳过任何已中止或仍在运行的事务ID。读者可以将此技术与参与事务的任意数量的分区或表一起使用,以实现原子性和对事务表的操作隔离。

                CRUD表中的原子性和隔离

                使用以下SQL语句创建完整的CRUD(创建,检索,更新,删除)事务表:
                  CREATE TABLE acidtbl (a INT, b STRING);
                  运行SHOW CREATE TABLE acidtbl提供有关默认值的信息:事务性(ACID)和ORC数据存储格式:
                    +----------------------------------------------------+
                    | createtab_stmt |
                    +----------------------------------------------------+
                    CREATE TABLE `acidtbl`(                            |
                    | `a` int, |
                    | `b` string) |
                    | ROW FORMAT SERDE |
                    | 'org.apache.hadoop.hive.ql.io.orc.OrcSerde' |
                    | STORED AS INPUTFORMAT |
                    | 'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' |
                    | OUTPUTFORMAT |
                    | 'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat' |
                    | LOCATION |
                    | 's3://myserver.com:8020/warehouse/tablespace/managed/hive/acidtbl' |
                    | TBLPROPERTIES ( |
                    | 'bucketing_version'='2', |
                    | 'transactional'='true', |
                    | 'transactional_properties'='default', |
                    | 'transient_lastDdlTime'='1555090610') |
                    +----------------------------------------------------+
                    支持更新和删除的表需要稍微不同的技术来实现原子性和隔离性。Hive在仅追加模式下运行,这意味着Hive不执行就地更新或删除。在就地更新或删除存在的情况下,无法隔离读取器和写入器。在这种情况下,需要使用锁管理器或其他机制进行隔离。这些机制为长期运行的查询带来了问题。
                    代替就地更新,Hive用行ID装饰每一行。行ID是一个 struct,由以下信息组成:

                    映射到创建行的事务的写ID

                    创建行的物理写入器的存储区ID(具有若干位信息的位支持整数)

                    行ID,在将行写入数据文件时对行进行编号

                    当发生删除时,Hive会将更改附加到表中,而不是就地删除。删除的数据将不可用,压缩过程将在以后处理垃圾回收。

                    创建操作

                    下面的示例将几行数据插入完整的CRUD事务表中,创建一个增量文件,并将行ID添加到数据文件中。
                      INSERT INTO acidtbl (a,b) VALUES (100"oranges"), (200"apples"), (300"bananas")

                      此操作将生成目录和文件delta_00001_00001 / bucket_0000,它们具有以下数据:


                      ROW_ID

                      a

                      b

                      {1,0,0}

                      100

                      "oranges"

                      {1,0.1}

                      200

                      "apples"

                      {1,0,2}

                      300

                      "bananas"

                      删除操作

                      与单行匹配的delete语句也会创建一个增量文件,称为delete-delta。该文件为与您的查询匹配的行存储了一组行ID。在读取时,读取器会查看此信息。当找到与行匹配的删除事件时,它将跳过该行,并且该行不包括在运算符管道中。下面的示例从事务表中删除数据:
                        DELETE FROM acidTbl where a = 200;
                        此操作将生成目录和文件delete_delta_00002_00002 / bucket_0000,它们具有以下数据:
                        ROW_ID

                        a

                        b

                        {1,0,1}

                        null

                        nul

                        更新操作

                        更新结合了新数据的删除和插入。下面的示例更新事务表:
                          UPDATE acidTbl SET b = "pears" where a = 300;
                          一个增量文件包含delete事件,另一个包含insert事件:
                          要求AcidInputFormat的读取器将应用所有插入事件,并封装所有逻辑以处理删除事件。读取操作首先从事务管理器获取快照信息,并根据快照信息选择与该读取操作相关的文件。接下来,该流程将每个数据文件拆分为每个流程必须处理的片段数。相关的删除事件被本地化到每个处理任务。删除事件存储在已排序的ORC文件中。压缩后的存储数据极少,这是Hive 3的显着优势。您不再需要担心增量文件中的插入事件会使网络饱和。


                          文章转载自大数据杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                          评论