hive原本不是用来做简单的crud的,但有时候我们就是有可能这么干,怎么办呢?
hive 还是提供了相应的功能的,查询是最必须的,就无须多说了。
插入数据一般来说都是大批量的插入,一般用于从源数据中导入数据到hive中,然后经过hive加工后,写入到一张新的结果表。而这个表的数据一般也会很大,具体看业务复杂性。
更新数据一般是不会被支持的,尤其是想更新某一条数据,但我们可以通过重新刷入数据的方式,达到更新数据的目的。一般hive表会有相应的分区要求,这样就可以做一定程度上的数据索引效果,以及减少大数据的量。而其底层存储为一个分区,一系列分组文件。
删除数据就更是没有了,不过与更新数据一样的道理,我们可以通过重新进行数据加工,刷入新数据集即可完成删除的目的。不过,要想剔除其中一条数据,这个加工逻辑得好好想想了。
1. select查询
这个最复杂的,也是最核心的。基本遵循sql92协议,也就是说基本上你会写sql, 就可以搞hive了。差别在于,hive会有很多自己支持的数据结构,以及很多特有的函数调用。另外,就是可以很方便地让用户自定义一些函数,以便满足业务需求。即udf. 因此,如果你不清楚这些udf如何使用,那么你就缺失了这方面的技能了。
举一个例子说明即可:
with a as ( select * from test_001 where pt='20210101' ), b as ( select * from test_002 where pt='20200101' ) select trim(a.name) name, a.t_map['field1'] map_f1, COALESCE(t1.f2, t2.f2) f2, case when t1.money>1000 then 'G' else 'H' end from a join b on a.uid = b.uid
总之一句话,你可以用sql表达非常复杂的业务逻辑。比如数据开发同学的重要利器就是这玩意。从一定角度上说,sql也是一门编程开发语言!骄傲了!
2. insert数据插入
hive之类的大数据处理工具,一般只会支持大批量的插入。为什么呢?因为它的底层存储就是一个个地大文件,方便实现啊,效率高啊啥的!所以,一般地,又会多出来一个概念,分区!因为是一个个地文件,在处理的时候,能做确定数据在哪个文件上,那么它效率就会很高了。
而像关系型数据库的索引之类的东西,这些大数据工具就不太方便有了,为什么呢?因为有大量的数据存储着,如果想要专门去建立索引,那么这个存储成本啊运算成本啊啥的,肯定就上去了。而最后可能还没有啥收益,因为我们更多地是做离线分析,并非差那几秒的性能,所以干脆不要了。
先来看几个map类型的数据操作方式:
-- 一个泛型的map, 只要给定的值类型正确,就会得到正确类型的map了 -- map<string,string>, map<string,double>, map<string,int> map('k', 'v1'); map('k', v1); map('k', v1); -- 将字符串转换为map形式,需要自行定义明确的分隔符 -- 注意,json并不能很好地转换为map形式 -- 以下结果为: {""b"":"2}","{"a"":""1""} select str_to_map('{"a":"1","b":2}') from dual; -- 以下结果为: {"a":"","b":"2"} select str_to_map('a:,b:2') from dual; -- 以下结果为: {"a":"1","b":"2"} select map('a','1','b','2') from dual; 接下来,我们来看下数据插入方式: -- 从加工数据集中写入全量表 insert into table xxx select k1,k2,k3 from a_xxx; -- 从加工数据集中覆盖式写入全量表 insert overwrite table xxx select * from a_xxx; insert into table xxx partition(pt='xxx') select k1,k2,k3 from a_xxx; insert into table xxx partition(pt='xxx') select k1,k2,k3 from a_xxx; -- 将加工结果集创建一个新表写入 create table tableName ROW FORMAT delimited fields terminated by ',' stored as textfile as with a as (select * from t1 where pt='xxx') select a.uid from a -- 插入一条条单独的记录 insert into values (v11, v12, v13), (v22, v22, v23); -- 另外一种插入单条记录的方式,从虚表中选择常量集 insert into table xxx select k1,k2,k3 from dual;
3. 数据更新
update数据与delete数据同sql标准协议,并无二致,但需要hive版本大于 0.14,且需要开启相应选项才可以。即需要支持hive的事务特性。
-- update数据与delete数据同sql标准协议 UPDATE tablename SET column = value [, column = value ...] [WHERE expression] DELETE FROM tablename [WHERE expression]
4. 创建表操作
创建表的方式与sql标签协议一致,只是有些特有类型可以使用,比如 map, struct...
-- 创建数据库 CREATE (DATABASE|SCHEMA) [IF NOT EXISTS] database_name [COMMENT database_comment] [LOCATION hdfs_path] [MANAGEDLOCATION hdfs_path] [WITH DBPROPERTIES (property_name=property_value, ...)]; -- 删除数据库 DROP (DATABASE|SCHEMA) [IF EXISTS] database_name [RESTRICT|CASCADE]; -- 创建表 CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name -- (Note: TEMPORARY available in Hive 0.14.0 and later) [(col_name data_type [column_constraint_specification] [COMMENT col_comment], ... [constraint_specification])] [COMMENT table_comment] [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] [SKEWED BY (col_name, col_name, ...) -- (Note: Available in Hive 0.10.0 and later)] ON ((col_value, col_value, ...), (col_value, col_value, ...), ...) [STORED AS DIRECTORIES] [ [ROW FORMAT row_format] [STORED AS file_format] | STORED BY 'storage.handler.class.name' [WITH SERDEPROPERTIES (...)] -- (Note: Available in Hive 0.6.0 and later) ] [LOCATION hdfs_path] [TBLPROPERTIES (property_name=property_value, ...)] -- (Note: Available in Hive 0.6.0 and later) [AS select_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables) CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name LIKE existing_table_or_view_name [LOCATION hdfs_path]; data_type : primitive_type | array_type | map_type | struct_type | union_type -- (Note: Available in Hive 0.7.0 and later) primitive_type : TINYINT | SMALLINT | INT | BIGINT | BOOLEAN | FLOAT | DOUBLE | DOUBLE PRECISION -- (Note: Available in Hive 2.2.0 and later) | STRING | BINARY -- (Note: Available in Hive 0.8.0 and later) | TIMESTAMP -- (Note: Available in Hive 0.8.0 and later) | DECIMAL -- (Note: Available in Hive 0.11.0 and later) | DECIMAL(precision, scale) -- (Note: Available in Hive 0.13.0 and later) | DATE -- (Note: Available in Hive 0.12.0 and later) | VARCHAR -- (Note: Available in Hive 0.12.0 and later) | CHAR -- (Note: Available in Hive 0.13.0 and later) array_type : ARRAY < data_type > map_type : MAP < primitive_type, data_type > struct_type : STRUCT < col_name : data_type [COMMENT col_comment], ...> union_type : UNIONTYPE < data_type, data_type, ... > -- (Note: Available in Hive 0.7.0 and later) row_format : DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] [NULL DEFINED AS char] -- (Note: Available in Hive 0.13 and later) | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)] file_format: : SEQUENCEFILE | TEXTFILE -- (Default, depending on hive.default.fileformat configuration) | RCFILE -- (Note: Available in Hive 0.6.0 and later) | ORC -- (Note: Available in Hive 0.11.0 and later) | PARQUET -- (Note: Available in Hive 0.13.0 and later) | AVRO -- (Note: Available in Hive 0.14.0 and later) | JSONFILE -- (Note: Available in Hive 4.0.0 and later) | INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname column_constraint_specification: : [ PRIMARY KEY|UNIQUE|NOT NULL|DEFAULT [default_value]|CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ] default_value: : [ LITERAL|CURRENT_USER()|CURRENT_DATE()|CURRENT_TIMESTAMP()|NULL ] constraint_specification: : [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ] [, PRIMARY KEY (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ] [, CONSTRAINT constraint_name FOREIGN KEY (col_name, ...) REFERENCES table_name(col_name, ...) DISABLE NOVALIDATE [, CONSTRAINT constraint_name UNIQUE (col_name, ...) DISABLE NOVALIDATE RELY/NORELY ] [, CONSTRAINT constraint_name CHECK [check_expression] ENABLE|DISABLE NOVALIDATE RELY/NORELY ] -- 删除表 DROP TABLE [IF EXISTS] table_name [PURGE]; -- 表更名 ALTER TABLE table_name RENAME TO new_table_name; -- 添加分区 ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location'][, PARTITION partition_spec [LOCATION 'location'], ...]; -- 删除分区 ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec IGNORE PROTECTION;
本部分内容参考官网: https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
5. 总结
hive中对于数据类型要求还是比较严的,实际上大部分的关系型数据库对类型要求都还是比较严的(mysql除外,它几乎可以使用string型类型插入任意字段)。
在对数据进行插入操作时,需要注意数据类型,必要时做转换,如果不能做转换那么就需要换一种写法了。不过好在,hive对于简单类型的判定并不太严,比如 '1'与1 是相等的, 1.0 和 '1.0' 也都是可以的。而当我们使用presto进行操作时,则不会被支持,其要求的类型更严格。
总之,针对每种类型的数据库,都有其特有的要求,我往往都需要为各自做相应的适配。所谓的标准协议,也只能从一定程度上约束大家的行为。但也已经非常不错了,至少大家是在标准的周围,扩展特有的能力,以满足不同的业务场景。