LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
LOCAL
关键字表明从本地文件系统加载文件,省略则表明从 HDFS 上加载文件:从本地文件系统加载文件时, filepath
能够是绝对路径也能够是相对路径 (建议使用绝对路径);node
从 HDFS 加载文件时候,filepath
为文件完整的 URL 地址:如 hdfs://namenode:port/user/hive/project/ data1
git
filepath
能够是文件路径 (在这种状况下 Hive 会将文件移动到表中),也能够目录路径 (在这种状况下,Hive 会将该目录中的全部文件移动到表中);github
若是使用 OVERWRITE 关键字,则将删除目标表(或分区)的内容,使用新的数据填充;不使用此关键字,则数据以追加的方式加入;sql
加载的目标能够是表或分区。若是是分区表,则必须指定加载数据的分区;shell
加载文件的格式必须与建表时使用 STORED AS
指定的存储格式相同。数据库
使用建议:express
不管是本地路径仍是 URL 都建议使用完整的。虽然可使用不完整的 URL 地址,此时 Hive 将使用 hadoop 中的 fs.default.name 配置来推断地址,可是为避免没必要要的错误,建议使用完整的本地路径或 URL 地址;apache
加载对象是分区表时建议显示指定分区。在 Hive 3.0 以后,内部将加载 (LOAD) 重写为 INSERT AS SELECT,此时若是不指定分区,INSERT AS SELECT 将假设最后一组列是分区列,若是该列不是表定义的分区,它将抛出错误。为避免错误,仍是建议显示指定分区。app
新建分区表:oop
CREATE TABLE emp_ptn( empno INT, ename STRING, job STRING, mgr INT, hiredate TIMESTAMP, sal DECIMAL(7,2), comm DECIMAL(7,2) ) PARTITIONED BY (deptno INT) -- 按照部门编号进行分区 ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
从 HDFS 上加载数据到分区表:
LOAD DATA INPATH "hdfs://hadoop001:8020/mydir/emp.txt" OVERWRITE INTO TABLE emp_ptn PARTITION (deptno=20);
emp.txt 文件可在本仓库的 resources 目录中下载
加载后表中数据以下,分区列 deptno 所有赋值成 20:
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement; INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
Hive 0.13.0 开始,建表时能够经过使用 TBLPROPERTIES(“immutable”=“true”)来建立不可变表 (immutable table) ,若是不能够变表中存在数据,则 INSERT INTO 失败。(注:INSERT OVERWRITE 的语句不受 immutable
属性的影响);
能够对表或分区执行插入操做。若是表已分区,则必须经过指定全部分区列的值来指定表的特定分区;
从 Hive 1.1.0 开始,TABLE 关键字是可选的;
从 Hive 1.2.0 开始 ,能够采用 INSERT INTO tablename(z,x,c1) 指明插入列;
能够将 SELECT 语句的查询结果插入多个表(或分区),称为多表插入。语法以下:
FROM from_statement INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ... [IF NOT EXISTS]] select_statement2] [INSERT INTO TABLE tablename2 [PARTITION ...] select_statement2] ...;
INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement; INSERT INTO TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement;
在向分区表插入数据时候,分区列名是必须的,可是列值是可选的。若是给出了分区列值,咱们将其称为静态分区,不然它是动态分区。动态分区列必须在 SELECT 语句的列中最后指定,而且与它们在 PARTITION() 子句中出现的顺序相同。
注意:Hive 0.9.0 以前的版本动态分区插入是默认禁用的,而 0.9.0 以后的版本则默认启用。如下是动态分区的相关配置:
配置 | 默认值 | 说明 |
---|---|---|
hive.exec.dynamic.partition |
true |
须要设置为 true 才能启用动态分区插入 |
hive.exec.dynamic.partition.mode |
strict |
在严格模式 (strict) 下,用户必须至少指定一个静态分区,以防用户意外覆盖全部分区,在非严格模式下,容许全部分区都是动态的 |
hive.exec.max.dynamic.partitions.pernode |
100 | 容许在每一个 mapper/reducer 节点中建立的最大动态分区数 |
hive.exec.max.dynamic.partitions |
1000 | 容许总共建立的最大动态分区数 |
hive.exec.max.created.files |
100000 | 做业中全部 mapper/reducer 建立的 HDFS 文件的最大数量 |
hive.error.on.empty.partition |
false |
若是动态分区插入生成空结果,是否抛出异常 |
CREATE TABLE emp( empno INT, ename STRING, job STRING, mgr INT, hiredate TIMESTAMP, sal DECIMAL(7,2), comm DECIMAL(7,2), deptno INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t"; -- 加载数据到 emp 表中 这里直接从本地加载 load data local inpath "/usr/file/emp.txt" into table emp;
完成后 emp
表中数据以下:
emp_ptn
表中加载的数据:TRUNCATE TABLE emp_ptn;
emp
表中查询部门编号为 20 的员工数据,并插入 emp_ptn
表中,语句以下:INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno=20) SELECT empno,ename,job,mgr,hiredate,sal,comm FROM emp WHERE deptno=20;
完成后 emp_ptn
表中数据以下:
-- 因为咱们只有一个分区,且仍是动态分区,因此须要关闭严格默认。由于在严格模式下,用户必须至少指定一个静态分区 set hive.exec.dynamic.partition.mode=nonstrict; -- 动态分区 此时查询语句的最后一列为动态分区列,即 deptno INSERT OVERWRITE TABLE emp_ptn PARTITION (deptno) SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp WHERE deptno=30;
完成后 emp_ptn
表中数据以下:
INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES ( value [, value ...] )
更新和删除的语法比较简单,和关系型数据库一致。须要注意的是这两个操做都只能在支持 ACID 的表,也就是事务表上才能执行。
-- 更新 UPDATE tablename SET column = value [, column = value ...] [WHERE expression] --删除 DELETE FROM tablename [WHERE expression]
1. 修改配置
首先须要更改 hive-site.xml
,添加以下配置,开启事务支持,配置完成后须要重启 Hive 服务。
<property> <name>hive.support.concurrency</name> <value>true</value> </property> <property> <name>hive.enforce.bucketing</name> <value>true</value> </property> <property> <name>hive.exec.dynamic.partition.mode</name> <value>nonstrict</value> </property> <property> <name>hive.txn.manager</name> <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value> </property> <property> <name>hive.compactor.initiator.on</name> <value>true</value> </property> <property> <name>hive.in.test</name> <value>true</value> </property>
2. 建立测试表
建立用于测试的事务表,建表时候指定属性 transactional = true
则表明该表是事务表。须要注意的是,按照官方文档 的说明,目前 Hive 中的事务表有如下限制:
CREATE TABLE emp_ts( empno int, ename String ) CLUSTERED BY (empno) INTO 2 BUCKETS STORED AS ORC TBLPROPERTIES ("transactional"="true");
3. 插入测试数据
INSERT INTO TABLE emp_ts VALUES (1,"ming"),(2,"hong");
插入数据依靠的是 MapReduce 做业,执行成功后数据以下:
4. 测试更新和删除
--更新数据 UPDATE emp_ts SET ename = "lan" WHERE empno=1; --删除数据 DELETE FROM emp_ts WHERE empno=2;
更新和删除数据依靠的也是 MapReduce 做业,执行成功后数据以下:
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 [ROW FORMAT row_format] [STORED AS file_format] SELECT ... FROM ...
OVERWRITE 关键字表示输出文件存在时,先删除后再从新写入;
和 Load 语句同样,建议不管是本地路径仍是 URL 地址都使用完整的;
写入文件系统的数据被序列化为文本,其中列默认由^A 分隔,行由换行符分隔。若是列不是基本类型,则将其序列化为 JSON 格式。其中行分隔符不容许自定义,但列分隔符能够自定义,以下:
-- 定义列分隔符为'\t' insert overwrite local directory './test-04' row format delimited FIELDS TERMINATED BY '\t' COLLECTION ITEMS TERMINATED BY ',' MAP KEYS TERMINATED BY ':' select * from src;
这里咱们将上面建立的 emp_ptn
表导出到本地文件系统,语句以下:
INSERT OVERWRITE LOCAL DIRECTORY '/usr/file/ouput' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' SELECT * FROM emp_ptn;
导出结果以下:
更多大数据系列文章能够参见 GitHub 开源项目: 大数据入门指南