Hive分区的概念与传统关系型数据库分区不同。
传统数据库的分区方式:就oracle而言,分区独立存在于段里,里面存储真实的数据,在数据进行插入的时候自动分配分区。
Hive的分区方式:由于Hive实际是存储在HDFS上的抽象,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。
静态分区 一级分区 创建 Hive分区是在创建表的时候用Partitioned by 关键字定义的,但要注意,Partitioned by子句中定义的列是表中正式的列,但是Hive下的数据文件中并不包含这些列,因为它们是目录名。注意:分区字段不能和表中的字段重复。
1 2 3 [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] 一级分区:一个目录 多级分区:多个目录
1 2 3 4 5 6 7 8 9 10 CREATE TABLE `emp_partition`( `empno` int, `ename` string, `job` string, `mgr` int, `hiredate` string, `sal` double, `comm` double ) partitioned by (deptno string) row format delimited fields terminated by '\t';
通过desc查看的表结构如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 hive (hive)> desc emp_partition; OK col_name data_type comment empno int ename string job string mgr int hiredate string sal double comm double deptno string # Partition Information # col_name data_type comment deptno string Time taken: 0.546 seconds, Fetched: 12 row(s)
插入数据 1 2 3 4 格式1: INSERT INTO TABLE tablename [PARTITION (partcol1[=val1], partcol2[=val2] ...)] VALUES values_row [, values_row …]; 格式2: load data local inpath '/home/hadoop/data/emp_10.txt' into table emp_partition partition (deptno=10);
从其他表中插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 hive (hive)> select * from emp; OK emp.empno emp.ename emp.job emp.mgr emp.hiredate emp.sal emp.comm emp.deptno 7369 SMITH CLERK 7902 1980-12-17 800.0 NULL 20 7499 ALLEN SALESMAN 7698 1981-2-20 1600.0 300.0 30 7521 WARD SALESMAN 7698 1981-2-22 1250.0 500.0 30 7566 JONES MANAGER 7839 1981-4-2 2975.0 NULL 20 7654 MARTIN SALESMAN 7698 1981-9-28 1250.0 1400.0 30 7698 BLAKE MANAGER 7839 1981-5-1 2850.0 NULL 30 7782 CLARK MANAGER 7839 1981-6-9 2450.0 NULL 10 7788 SCOTT ANALYST 7566 1987-4-19 3000.0 NULL 20 7839 KING PRESIDENT NULL 1981-11-17 5000.0 NULL 10 7844 TURNER SALESMAN 7698 1981-9-8 1500.0 0.0 30 7876 ADAMS CLERK 7788 1987-5-23 1100.0 NULL 20 7900 JAMES CLERK 7698 1981-12-3 950.0 NULL 30 7902 FORD ANALYST 7566 1981-12-3 3000.0 NULL 20 7934 MILLER CLERK 7782 1982-1-23 1300.0 NULL 10 Time taken: 0.269 seconds, Fetched: 14 row(s) hive (hive)> insert into emp_partition partition(deptno=30) select empno,ename,job,mgr,hiredate,sal,comm from emp where deptno=10;
从文件加载数据到表中(不包含分区列字段)
1 2 [hadoop@hadoop001 data]$ cat emp_10.txt 88 KK SALESMAN 8888 1998-10-14 5000 500
1 hive (hive)> load data local inpath '/home/hadoop/data/emp_10.txt' into table emp_partition partition (deptno=10);
查看数据 利用分区表查询:(一般分区表都是利用where语句查询的)
1 2 3 4 5 6 7 8 hive (hive)> select * from emp_partition where deptno=10; OK emp_partition.empno emp_partition.ename emp_partition.job emp_partition.mgr emp_partition.hiredate emp_partition.sal emp_partition.comm emp_partition.deptno 7782 CLARK MANAGER 7839 1981-6-9 2450.0 NULL 10 7839 KING PRESIDENT NULL 1981-11-17 5000.0 NULL 10 7934 MILLER CLERK 7782 1982-1-23 1300.0 NULL 10 88 KK SALESMAN 8888 1998-10-14 5000.0 500.0 10 Time taken: 0.25 seconds, Fetched: 4 row(s)
查看hdfs上emp_partition表目录结构,可以看到在以表名目录下,有以deptno=10(分区名)的子目录存放着真实的数据文件
1 2 3 [hadoop@hadoop001 data]$ hadoop fs -ls -R /user/hive/warehouse/hive.db/emp_partition drwxr-xr-x - hadoop supergroup 0 2021-12-28 14:01 /user/hive/warehouse/hive.db/emp_partition/deptno=10 -rw-r--r-- 1 hadoop supergroup 130 2021-12-28 14:01 /user/hive/warehouse/hive.db/emp_partition/deptno=10/000000_0
同理,插入deptno为20,30的数据。
1 2 3 4 5 6 7 8 [hadoop@hadoop001 data]$ hadoop fs -ls -R /user/hive/warehouse/hive.db/emp_partition drwxr-xr-x - hadoop supergroup 0 2021-12-28 12:12 /user/hive/warehouse/hive.db/emp_partition/deptno=10 -rw-r--r-- 1 hadoop supergroup 130 2021-12-28 14:01 /user/hive/warehouse/hive.db/emp_partition/deptno=10/000000_0 -rw-r--r-- 1 hadoop supergroup 40 2021-12-28 12:12 /user/hive/warehouse/hive.db/emp_partition/deptno=10/emp_10.txt drwxr-xr-x - hadoop supergroup 0 2021-12-28 14:01 /user/hive/warehouse/hive.db/emp_partition/deptno=20 -rw-r--r-- 1 hadoop supergroup 214 2021-12-28 14:01 /user/hive/warehouse/hive.db/emp_partition/deptno=20/000000_0 drwxr-xr-x - hadoop supergroup 0 2021-12-28 12:11 /user/hive/warehouse/hive.db/emp_partition/deptno=30 -rw-r--r-- 1 hadoop supergroup 40 2021-12-28 12:11 /user/hive/warehouse/hive.db/emp_partition/deptno=30/000000_0
查看分区 1 2 3 4 5 6 7 hive (hive)> show partitions emp_partition; OK partition deptno=10 deptno=20 deptno=30 Time taken: 0.152 seconds, Fetched: 3 row(s)
添加分区 1 2 3 4 5 6 7 8 9 10 11 hive (hive)> alter table emp_partition add partition (deptno=40); OK Time taken: 0.282 seconds hive (hive)> show partitions emp_partition; OK partition deptno=10 deptno=20 deptno=30 deptno=40 Time taken: 0.127 seconds, Fetched: 4 row(s)
删除分区(删除相应分区文件) 注意,对于外表进行drop partition并不会删除hdfs上的文件,并且可以通过msck repair table table_name
同步hdfs上的分区。
1 alter table emp_partition drop partition (deptno = 40);
修复分区 修复分区就是重新同步hdfs上的分区信息。(外部表在hdfs目录上添加文件后使用)
1 msck repair table table_name [ADD/DROP/SYNC PARTITIONS];
在hive3.0中msck命令支持删除partition信息。
多级分区 多分区表装载数据时,分区字段必须都要加。如果只有一个,会报错。
下面创建一张静态分区表par_tab_muilt,多个分区(性别+日期)
1 2 hive (hive)> create table par_tab_muilt (name string, nation string) partitioned by (sex string,dt string) row format delimited fields terminated by ',' ; hive (hive)> load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab_muilt partition (sex='man',dt='2021-12-28');
1 2 3 4 [hadoop@hadoop001 files]$ hadoop fs -ls -R /user/hive/warehouse/par_tab_muilt drwxr-xr-x - hadoop supergroup 0 2021-12-28 08:45 /user/hive/warehouse/par_tab_muilt/sex=man drwxr-xr-x - hadoop supergroup 0 2021-12-28 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2021-12-28 -rwxr-xr-x 1 hadoop supergroup 71 2021-12-28 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2021-12-28/par_tab.txt
可见,新建表的时候定义的分区顺序,决定了文件目录顺序(谁是父目录谁是子目录),正因为有了这个层级关系,当我们查询所有man的时候,man以下的所有日期下的数据都会被查出来。如果只查询日期分区,但父目录sex=man和sex=woman都有该日期的数据,那么Hive会对输入路径进行修剪,从而只扫描日期分区,性别分区不作过滤(即查询结果包含了所有性别)。
动态分区 为什么要使用动态分区呢,我们举个例子,假如中国有50个省,每个省有50个市,每个市都有100个区,那我们都要使用静态分区要使用多久才能搞完。所有我们要使用动态分区。
注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区。
动态分区可以允许所有的分区列都是动态分区列,但是要首先设置一个参数hive.exec.dynamic.partition.mode
动态分区默认是没有开启。开启后默认是以严格模式执行的,在这种模式下需要至少一个分区字段是静态的。这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。这有助于阻止因设计错误导致导致查询差生大量的分区。列如:用户可能错误使用时间戳作为分区表字段。然后导致每秒都对应一个分区!这样我们也可以采用相应的措施:
1 2 关闭严格分区模式 set hive.exec.dynamic.partition.mode=nonstrict //分区模式,默认strict(至少有一个分区列是静态分区) 开启支持动态分区 set hive.exec.dynamic.partition=true //开启动态分区,默认true
1 2 3 4 其他相关参数 : set hive.exec.max.dynamic.partitions.pernode; #每一个执行mr节点上,允许创建的动态分区的最大数量(100) set hive.exec.max.dynamic.partitions; #所有执行mr节点上,允许创建的所有动态分区的最大数量(1000) set hive.exec.max.created.files; #所有的mr job允许创建的文件的最大数量(100000)
利用动态分区,我们可以一次完成插入上面例子中deptno不同的数据的操作
1 insert overwrite table emp_partition partition(deptno) select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp;
补充 注意事项
hive的分区使用的表外字段,分区字段是一个伪列但是可以查询过滤。
分区字段不建议使用中文.
不太建议使用动态分区。因为动态分区将会使用mapreduce来查询数据,如果分区数量过多将导致namenode和yarn的资源瓶颈。所以建议动态分区前也尽可能之前预知分区数量。
分区属性的修改均可以使用手动元数据和hdfs的数据内容
外部分区表 外部表同样可以使用分区,事实上,用户会发现,只是管理大型生产数据集最常见的情况,这种结合给用户提供一个和其他工具共享数据的方式,同时也可以优化查询性能。这样我们就可以把数据路径改变而不影响数据的丢失,这是内部分区表远远不能做的事情:
1 2 3 4 5 6 7 8 9 10 11 12 1,(因为我们创建的是外部表)所有我们可以把表数据放到hdfs上的随便一个地方这里自动数据加载到/user/had/data/下(当然我们之前在外部表上指定了路径) load data local inpath '/home/had/data.txt' into table employees_ex partition (country="china",state="Asia"); 2,如果我们加载的数据要分离一些旧数据的时候就可以hadoop的distcp命令来copy数据到某个路径 hadoop distcp /user/had/data/country=china/state=Asia /user/had/data_old/country=china/state=Asia 3,修改表,把移走的数据的路径在hive里修改 alter table employees partition(country="china",state="Asia") set location '/user/had/data_old/country=china/state=Asia' 4,使用hdfs的rm命令删除之前路径的数据 hdfs dfs -rmr /user/had/data/country=china/state=Asia 这样我们就完成一次数据迁移 如果觉得突然忘记了数据的位置使用使用下面的方式查看 describe extend employees_ex partition (country="china",state="Asia");
众多的修改语句 1 2 3 4 5 6 7 8 9 10 11 1,把一个分区打包成一个har包 alter table employees archive partition (country="china",state="Asia") 2, 把一个分区har包还原成原来的分区 alter table employees unarchive partition (country="china",state="Asia") 3, 保护分区防止被删除 alter table employees partition (country="china",state="Asia") enable no_drop 4,保护分区防止被查询 alter table employees partition (country="china",state="Asia") enable offline 5,允许分区删除和查询 alter table employees partition (country="china",state="Asia") disable no_drop alter table employees partition (country="china",state="Asia") disable offline
参考链接:
https://www.cnblogs.com/yongjian/archive/2017/03/29/6640951.html
https://blog.csdn.net/weixin_41122339/article/details/81584110
https://blog.csdn.net/lixinkuan328/article/details/102103237