HiveQL DDL—分区

本文详细介绍了Hive中分区表的创建、管理及优化方法,包括如何通过创建分区提高查询性能,以及如何进行分区的增删改查等操作。

概述

  默认情况下,一个简单的HQL查询扫描整个表,这对于大表来说查询性能会非常低。通过创建分区解决很好的解决这类问题,分区与RDBMS 中的分区非常相似。在Hive中,每个分区对应一个预定义的分区列,该列会映射到HDFS中表目录中的子目录。查询表中数据时,只读取所需的数据分区(目录),这就会大大减少查询的I/O和时间。在Hive中使用分区是提高性能的一种非常简单有效的方法。

创建分区表

  分区表的创建语法是在创建普通表的基础上多了 PARTITIONED BY 子句来指定分区字段。
  示例

> CREATE TABLE employee_partitioned (
name STRING,
work_place ARRAY<STRING>,
gender_age STRUCT<gender:STRING,age:INT>,
skills_score MAP<STRING,INT>,
depart_title MAP<STRING,ARRAY<STRING>>
)
PARTITIONED BY (year INT, month INT) -- partition column
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '|'
COLLECTION ITEMS TERMINATED BY ','
MAP KEYS TERMINATED BY ':';

> desc employee_partitioned;
+--------------------------+--------------------------------+----------+
|         col_name         |           data_type            | comment  |
+--------------------------+--------------------------------+----------+
| name                     | string                         |          |
| work_place               | array<string>                  |          |
| gender_age               | struct<gender:string,age:int>  |          |
| skills_score             | map<string,int>                |          |
| depart_title             | map<string,array<string>>      |          |
| year                     | int                            |          |
| month                    | int                            |          |
|                          | NULL                           | NULL     |
| # Partition Information  | NULL                           | NULL     |
| # col_name               | data_type                      | comment  |
| year                     | int                            |          |
| month                    | int                            |          |
+--------------------------+--------------------------------+----------+

  加载数据

> LOAD DATA INPATH '/tmp/employee1.txt'
OVERWRITE INTO TABLE employee_partitioned
PARTITION (year=2018, month=11);

> LOAD DATA INPATH '/tmp/employee2.txt'
OVERWRITE INTO TABLE employee_partitioned
PARTITION (year=2018, month=12);

查看分区

使用SHOW查看分区

查看表的所有分区

SHOW PARTITIONS table_name;

  SHOW PARTITIONS会列出表中所有已存在的分区,分区会按照字母表顺序列出。
  示例

> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
+---------------------+

查看部分分区

  示例:使用分区的部分说明信息(partition specification)过滤结果。

> SHOW PARTITIONS employee_partitioned PARTITION(month='11');
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
+---------------------+

查看分区的扩展信息

SHOW TABLE EXTENDED [IN|FROM database_name] LIKE 'identifier_with_wildcards' PARTITION(partition_spec);

  查看分区的扩展信息时,将不支持表名是正则表达式,而且分区的说明信息必须是完整的信息,不能只有部分分区信息。
  示例

> SHOW TABLE EXTENDED LIKE "employee_partitioned"  PARTITION (year='2018',month='11');
+----------------------------------------------------+
|                      tab_name                      |
+----------------------------------------------------+
| tableName:employee_partitioned                     |
| owner:hadoop                                       |
| location:hdfs://ns001/tmp/hive/employee_partitioned/year=2018/month=11 |
| inputformat:org.apache.hadoop.mapred.TextInputFormat |
| outputformat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat |
| columns:struct columns { string name, list<string> work_place, struct<gender:string,age:i32> gender_age, map<string,i32> skills_score, map<string,list<string>> depart_title} |
| partitioned:true                                   |
| partitionColumns:struct partition_columns { i32 year, i32 month} |
| totalNumberFiles:1                                 |
| totalFileSize:228                                  |
| maxFileSize:228                                    |
| minFileSize:228                                    |
| lastAccessTime:1569484958041                       |
| lastUpdateTime:1569484989618                       |
|                                                    |
+----------------------------------------------------+

使用DESCRIBE查看分区

  适用于 Hive 1.x.x 和 0.x.x

--不指定数据库时,字段和表名使用一个点(DOT)分隔
DESCRIBE [EXTENDED|FORMATTED] table_name[.column_name] PARTITION partition_spec;
--指定数据库时,字段和表名使用空格分隔
DESCRIBE [EXTENDED|FORMATTED] [db_name.]table_name [column_name] PARTITION partition_spec;

  适用于Hive2.0 以后

-- 不支持字段和表名使用一个点(DOT)分隔这种格式
-- 分区说明信息是在表名之后、字段之前;之前的版本中,字段信息在表名和分区说明之间。
-- field_name用于struct,'$elem$'用于array,'$key$'用于map的key,'$value$'用于map的value
DESCRIBE [EXTENDED | FORMATTED]
    [db_name.]table_name PARTITION partition_spec [col_name ( [.field_name] | [.'$elem$'] | [.'$key$'] | [.'$value$'] )* ];

  示例

> DESCRIBE  employee_partitioned PARTITION (year='2018',month='11');
+--------------------------+--------------------------------+----------+
|         col_name         |           data_type            | comment  |
+--------------------------+--------------------------------+----------+
| name                     | string                         |          |
| work_place               | array<string>                  |          |
| gender_age               | struct<gender:string,age:int>  |          |
| skills_score             | map<string,int>                |          |
| depart_title             | map<string,array<string>>      |          |
| year                     | int                            |          |
| month                    | int                            |          |
|                          | NULL                           | NULL     |
| # Partition Information  | NULL                           | NULL     |
| # col_name               | data_type                      | comment  |
| year                     | int                            |          |
| month                    | int                            |          |
+--------------------------+--------------------------------+----------+

> DESCRIBE  employee_partitioned  PARTITION (year='2018',month='11') skills_score.$value$;
+-----------+------------+--------------------+
| col_name  | data_type  |      comment       |
+-----------+------------+--------------------+
| $value$   | int        | from deserializer  |
+-----------+------------+--------------------+

  如果使用EXTENDED关键字,则以Thrift序列化形式显示表的元数据,通常用于调试。如果使用 FORMATTED 关键字,则以表格形式显示元数据。

> DESCRIBE FORMATTED employee_partitioned PARTITION (year='2018',month='11');
+---------------------------------+----------------------------------------------------+----------+
|            col_name             |                     data_type                      | comment  |
+---------------------------------+----------------------------------------------------+----------+
| name                            | string                                             |          |
| work_place                      | array<string>                                      |          |
| gender_age                      | struct<gender:string,age:int>                      |          |
| skills_score                    | map<string,int>                                    |          |
| depart_title                    | map<string,array<string>>                          |          |
| year                            | int                                                |          |
| month                           | int                                                |          |
|                                 | NULL                                               | NULL     |
| # Partition Information         | NULL                                               | NULL     |
| # col_name                      | data_type                                          | comment  |
| year                            | int                                                |          |
| month                           | int                                                |          |
|                                 | NULL                                               | NULL     |
| Detailed Partition Information  | Partition(values:[2018, 11], dbName:test2, tableName:employee_partitioned, createTime:1569484989, lastAccessTime:0, sd:StorageDescriptor(cols:[FieldSchema(name:name, type:string, comment:null), FieldSchema(name:work_place, type:array<string>, comment:null), FieldSchema(name:gender_age, type:struct<gender:string,age:int>, comment:null), FieldSchema(name:skills_score, type:map<string,int>, comment:null), FieldSchema(name:depart_title, type:map<string,array<string>>, comment:null), FieldSchema(name:year, type:int, comment:null), FieldSchema(name:month, type:int, comment:null)], location:hdfs://ns001/tmp/hive/employee_partitioned/year=2018/month=11, inputFormat:org.apache.hadoop.mapred.TextInputFormat, outputFormat:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat, compressed:false, numBuckets:-1, serdeInfo:SerDeInfo(name:null, serializationLib:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe, parameters:{mapkey.delim=:, collection.delim=,, serialization.format=|, field.delim=|}), bucketCols:[], sortCols:[], parameters:{}, skewedInfo:SkewedInfo(skewedColNames:[], skewedColValues:[], skewedColValueLocationMaps:{}), storedAsSubDirectories:false), parameters:{transient_lastDdlTime=1569484989, totalSize=228, numRows=0, rawDataSize=0, numFiles=1}, catName:hive, writeId:0) |          |
+---------------------------------+----------------------------------------------------+----------+

> DESCRIBE FORMATTED employee_partitioned  PARTITION (year='2018',month='11') skills_score.$value$;
+-------------+------------+--------------------+-------+------------+-----------------+--------------+--------------+------------+-------------+------------+----------+
|  col_name   | data_type  |        min         |  max  | num_nulls  | distinct_count  | avg_col_len  | max_col_len  | num_trues  | num_falses  | bitvector  | comment  |
+-------------+------------+--------------------+-------+------------+-----------------+--------------+--------------+------------+-------------+------------+----------+
| # col_name  | data_type  | comment            | NULL  | NULL       | NULL            | NULL         | NULL         | NULL       | NULL        | NULL       | NULL     |
| $value$     | int        | from deserializer  | NULL  | NULL       | NULL            | NULL         | NULL         | NULL       | NULL        | NULL       | NULL     |
+-------------+------------+--------------------+-------+------------+-----------------+--------------+--------------+------------+-------------+------------+----------+

修改分区

添加字段

  添加字段的操作在表的DDL中已经描述过。只是默认的添加字段只是修改表的元数据,不会对已经存在的分区产生影响。也就是说在默认情况下,添加的字段只会对新建的分区有影响。如果需要对所有的分区同时添加字段,只需要使用CASCADE关键字。
  示例

> ALTER TABLE employee_partitioned ADD COLUMNS (work string) CASCADE;
> DESCRIBE  employee_partitioned PARTITION (year='2018',month='11');
+--------------------------+--------------------------------+----------+
|         col_name         |           data_type            | comment  |
+--------------------------+--------------------------------+----------+
| name                     | string                         |          |
| work_place               | array<string>                  |          |
| gender_age               | struct<gender:string,age:int>  |          |
| skills_score             | map<string,int>                |          |
| depart_title             | map<string,array<string>>      |          |
| work                     | string                         |          |
| year                     | int                            |          |
| month                    | int                            |          |
|                          | NULL                           | NULL     |
| # Partition Information  | NULL                           | NULL     |
| # col_name               | data_type                      | comment  |
| year                     | int                            |          |
| month                    | int                            |          |
+--------------------------+--------------------------------+----------+

添加分区

ALTER TABLE table_name ADD [IF NOT EXISTS] PARTITION partition_spec [LOCATION 'location'][, PARTITION partition_spec [LOCATION 'location'], ...];
 
partition_spec:
  : (partition_column = partition_col_value, partition_column = partition_col_value, ...)

  使用ALTER TABLE ADD PARTITION给表添加分区。只有分区值是字符串时,才需要被引号包围。Location必须是一个内部存有数据文件的目录。(ADD PARTITION只是更改表的元数据,但不会加载数据。如果分区的位置不存在数据,查询将不会返回任何结果。如果要添加的分区表中已经存在,则会报错。使用IF NOT EXISTS可以跳过错误。

  示例

> ALTER TABLE employee_partitioned ADD IF NOT EXISTS PARTITION (year=2019,month=01);
> show partitions employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
| year=2019/month=1   |
+---------------------+

修改分区名

ALTER TABLE table_name PARTITION partition_spec RENAME TO PARTITION partition_spec;

  示例

> ALTER TABLE employee_partitioned PARTITION (year=2019,month=1) RENAME TO PARTITION (year=2019,month=2);
> show partitions employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
| year=2019/month=2   |
+---------------------+

交换分区

  分区可以在表之间进行交换(移动)

-- Move partition from table_name_1 to table_name_2
ALTER TABLE table_name_2 EXCHANGE PARTITION (partition_spec) WITH TABLE table_name_1;
-- multiple partitions
ALTER TABLE table_name_2 EXCHANGE PARTITION (partition_spec, partition_spec2, ...) WITH TABLE table_name_1;

  table_name_2 是目标表,table_name_1 是源表

  示例

> CREATE TABLE employee_partitioned_copy1 like employee_partitioned;
> ALTER TABLE employee_partitioned_copy1 EXCHANGE PARTITION (year=2019,month=2) WITH TABLE employee_partitioned;
> show partitions employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
+---------------------+
:> show partitions employee_partitioned_copy1;
+--------------------+
|     partition      |
+--------------------+
| year=2019/month=2  |
+--------------------+

修改分区字段的数据类型

  示例:将分区字段year的类型从int改为string

> ALTER TABLE employee_partitioned PARTITION COLUMN(year string);
> desC employee_partitioned;
+--------------------------+--------------------------------+----------+
|         col_name         |           data_type            | comment  |
+--------------------------+--------------------------------+----------+
| name                     | string                         |          |
| work_place               | array<string>                  |          |
| gender_age               | struct<gender:string,age:int>  |          |
| skills_score             | map<string,int>                |          |
| depart_title             | map<string,array<string>>      |          |
| work                     | string                         |          |
| year                     | string                         |          |
| month                    | int                            |          |
|                          | NULL                           | NULL     |
| # Partition Information  | NULL                           | NULL     |
| # col_name               | data_type                      | comment  |
| year                     | string                         |          |
| month                    | int                            |          |
+--------------------------+--------------------------------+----------+

修改分区的文件格式

  示例:将分区(year=‘2018’,month=‘12’)的文件格式从text改为ORC

> DESC FORMATTED employee_partitioned PARTITION (year='2018',month='12')
+-----------------------------------+----------------------------------------------------+-----------------------+
|             col_name              |                     data_type                      |        comment        |
+-----------------------------------+----------------------------------------------------+-----------------------+
       ...
| # Storage Information             | NULL                                               | NULL                  |
| SerDe Library:                    | org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe | NULL                  |
| InputFormat:                      | org.apache.hadoop.mapred.TextInputFormat           | NULL                  |
| OutputFormat:                     | org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat | NULL                  |
...
+-----------------------------------+----------------------------------------------------+-----------------------+
> ALTER TABLE employee_partitioned PARTITION (year='2018',month='12') SET FILEFORMAT ORC;
> DESC FORMATTED employee_partitioned PARTITION (year='2018',month='12');
+-----------------------------------+----------------------------------------------------+-----------------------+
|             col_name              |                     data_type                      |        comment        |
+-----------------------------------+----------------------------------------------------+-----------------------+
...
| # Storage Information             | NULL                                               | NULL                  |
| SerDe Library:                    | org.apache.hadoop.hive.ql.io.orc.OrcSerde          | NULL                  |
| InputFormat:                      | org.apache.hadoop.hive.ql.io.orc.OrcInputFormat    | NULL                  |
| OutputFormat:                     | org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat   | NULL                  |
...
+-----------------------------------+----------------------------------------------------+-----------------------+

注意:用户需要自己确定分区修改后的实际数据文件格式和修改相匹配。否则查询时会报错。实际上,单独去修改表的某个分区文件格式的应用场景会非常少。

修改分区的存储位置

  示例:修改分区(year=‘2018’,month=‘12’)的存储位置

> DESC FORMATTED employee_partitioned partition(year='2018',month='12')
+-----------------------------------+----------------------------------------------------+-----------------------+
|             col_name              |                     data_type                      |        comment        |
+-----------------------------------+----------------------------------------------------+-----------------------+
...
| Location:                         | hdfs://ns001/tmp/hive/employee_partitioned/year=2018/month=12 | NULL                  |
...
+-----------------------------------+----------------------------------------------------+-----------------------+
> ALTER TABLE employee_partitioned PARTITION (year='2018',month='12') SET LOCATION '/user/hive/warehouse/employee_partitioned/year=2018/month=12';
> DESC FORMATTED employee_partitioned partition(year='2018',month='11')
+-----------------------------------+----------------------------------------------------+-----------------------+
|             col_name              |                     data_type                      |        comment        |
+-----------------------------------+----------------------------------------------------+-----------------------+
...
| Location:                         | hdfs://ns001/tmp/hive/employee_partitioned/year=2018/month=11 | NULL                  |
...
+-----------------------------------+----------------------------------------------------+-----------------------+

注意:修改分区的存储位置并不会对已有的数据文件进行移动,用户需要自己确保数据文件符合分区的位置。

合并分区中的小文件

  在RCFile 或者 ORC存储格式的分区中,如果有很多的小文件,可以使用 CONCATENATE 选项对小文件进行合并。

  示例:对分区(year=‘2018’,month=‘12’)中的文件进行合并

ALTER TABLE employee_partitioned PARTITION (year='2018',month='12')  CONCATENATE;

清理分区

  清空分区有2种方式,一种使用DROP将分区及数据删除,另一种使用TRUNCATE只清空数据但保留分区元数据信息

DROP

ALTER TABLE table_name DROP [IF EXISTS] PARTITION partition_spec[, PARTITION partition_spec, ...]
  [IGNORE PROTECTION] [PURGE];            -- (Note: PURGE available in Hive 1.2.0 and later, IGNORE PROTECTION not available 2.0.0 and later) 

  示例:删除分区(year=‘2018’,month=‘12’)

> SHOW PARTITIONS employee_partitioned
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
+---------------------+
> ALTER TABLE employee_partitioned DROP IF EXISTS PARTITION (year='2018',month='12');
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
+---------------------+

TRUNCATE

  示例:清空分区(year=‘2018’,month=‘11’)中的数据

> TRUNCATE TABLE employee_partitioned PARTITION (year='2018',month='11');
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
+---------------------+

修复分区

  在使用Hive的时候,如果我们使用HDFS的命令(fs -put或者fs -rm)直接把数据放到分区表的数据目录下或者从数据目录中删除分区数据。此时Hive的元数据并不会感知到这个变化。因此即使分区表有实际数据,我们也无法查询出来。一种可行的方式是,我们可以为每一个新增的分区或是删除的分区执行 ALTER TABLE table_name ADD/DROP PARTITION 命令,使的元数据信息和实际数据的分布匹配。但是假设我们一次新增了很多的分区,使用这种方式一个一个的添加分区难免效率会很低,Hive提供了一个分区修复命令MSCK可以帮助我们一次性完成这样的操作。

MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];

  默认执行的操作是ADD PARTITIONS。DROP SYNC PARTITIONS选项将从metastore中删除分区(其数据已经从HDFS中删除)信息。SYNC PARTITIONS相当于同时执行ADD 和 DROP PARTITIONS。

  示例

  1. 查看分区employee_partitioned表当前的分区信息,只有一个分区
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
+---------------------+
  1. 使用HDFS命令在employee_partitioned的数据目录下添加子目录 year=2019/month=1 和 year=2019/month=2
hadoop fs -mkdir /tmp/hive/employee_partitioned/year=2019/month=1/
hadoop fs -mkdir /tmp/hive/employee_partitioned/year=2019/month=2/
  1. 然后执行MSCK命令添加分区
> MSCK REPAIR TABLE employee_partitioned ADD PARTITIONS;
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
| year=2019/month=1   |
| year=2019/month=2   |
+---------------------+

可以看到,分区变为了4个,其中year=2018/month=12是之前测试中未被删除的子目录,因此也被恢复了。

  1. 然后删除一个分区目录
hadoop fs -rm -r /tmp/hive/employee_partitioned/year=2019/month=1/
  1. 再次执行MSCK命令
> MSCK REPAIR  TABLE employee_partitioned DROP PARTITIONS;
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
| year=2019/month=2   |
+---------------------+

  注意,添加分区时,新增的目录结构必须符合分区表的分区定义规范,比如对于上述分区表employee_partitioned,新增的分区目录必须是year=xxx/month=yy 这种格式,如果是其他格式,MSCK将无法工作
  比如新增一个子目录year=2019/test=1

hadoop fs -mkdir /tmp/hive/employee_partitioned/year=2019/test=1

  执行MSCK命令

> MSCK REPAIR  TABLE employee_partitioned ADD PARTITIONS;
> SHOW PARTITIONS employee_partitioned;
+---------------------+
|      partition      |
+---------------------+
| year=2018/month=11  |
| year=2018/month=12  |
| year=2019/month=2   |
+---------------------+

  分区信息并无变化

  补充:执行MSCK命令时,如果出现错误:FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask,这是由于从Hive1.3开始,如果在HDFS上找到分区值中包含不允许的字符的目录,MSCK将引发异常。可以在会话中将配置项hive.msck.path.validation设置为ignore;

set hive.msck.path.validation=ignore;

参考
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
书籍 Apache Hive Essentials Second Edition (by Dayong Du) Chapter 3

<think>我们正在讨论HiveQL的数据定义部分。根据引用内容,HiveQL支持类似SQL的数据定义操作,但有一些特定的扩展和限制。下面我将详细解释HiveQL中数据定义的语法和功能。首先,HiveQL的数据定义主要包括数据库、表的创建、删除和修改等操作。由于Hive的底层基于Hadoop,因此它有一些特定的概念,如外部表、分区、分桶等。###1.数据库操作####创建数据库语法:```sqlCREATEDATABASE[IFNOTEXISTS]database_name[COMMENTdatabase_comment][LOCATIONhdfs_path][WITHDBPROPERTIES(property_name=property_value,...)];```-`IFNOTEXISTS`:可选,如果数据库已存在则不执行操作。-`COMMENT`:数据库的注释。-`LOCATION`:指定数据库在HDFS上的存储路径,如果不指定则使用默认路径。-`WITHDBPROPERTIES`:为数据库设置一些键值对属性。示例(参考引用[3]):```sqlCREATEDATABASEtest2COMMENT"createdatabase";CREATEDATABASEtestWITHDBPROPERTIES('name'='yjt','data'='2019-06-20');```####查看数据库```sqlDESCRIBEDATABASEdatabase_name;--显示数据库基本信息DESCRIBEDATABASEEXTENDEDdatabase_name;--显示数据库的详细信息(包括属性)```示例(引用[3]):```sqlDESCDATABASEtest1;--查看test1数据库的基本信息```####删除数据库```sqlDROPDATABASE[IFEXISTS]database_name[RESTRICT|CASCADE];```-`RESTRICT`:默认,如果数据库非空(含有表)则不允许删除。-`CASCADE`:强制删除数据库及其所有表。###2.表操作####创建表Hive支持两种类型的表:内部表(管理表)和外部表。-**内部表**:由Hive管理其数据和元数据。删除表时,数据也会被删除。-**外部表**:仅管理元数据,数据存储在外部位置(如HDFS)。删除表时,只删除元数据,不删除数据。创建内部表:```sqlCREATETABLE[IFNOTEXISTS]table_name(column_namedata_type[COMMENTcolumn_comment],...)[COMMENTtable_comment][PARTITIONEDBY(col_namedata_type[COMMENTcol_comment],...)]--分区[CLUSTEREDBY(col_name,col_name,...)[SORTEDBY(col_name[ASC|DESC],...)]INTOnum_bucketsBUCKETS]--分桶[ROWFORMATrow_format][STOREDASfile_format][LOCATIONhdfs_path];--如果不指定,将使用默认的数据库路径```创建外部表(引用[4]示例):```sqlCREATEEXTERNALTABLEIFNOTEXISTSstocks(indexINT,sourceINT,destinationINT,costINT)ROWFORMATDELIMITEDFIELDSTERMINATEDBY','LOCATION'/home/hadoop/workspace';```参数说明:-`ROWFORMATDELIMITED`:指定行格式,通常后面跟字段分隔符等。-`FIELDSTERMINATEDBY','`:指定字段分隔符,如逗号。-`STOREDAS`:指定文件存储格式(如TEXTFILE,SEQUENCEFILE,RCFILE等)。-`LOCATION`:指定表数据在HDFS上的存储路径(外部表必须指定,内部表可选)。####分区分区表可以将数据按某个列的值进行分区存储,提高查询效率。```sqlCREATETABLEtable_name(...)PARTITIONEDBY(partition_col1data_type,...);```注意:分区列不能是表中已定义的列。####查看表信息```sqlDESCRIBE[EXTENDED|FORMATTED]table_name;--查看表结构,EXTENDED或FORMATTED显示更详细信息```####删除表```sqlDROPTABLE[IFEXISTS]table_name;```###3.修改表Hive支持修改表结构,但限制较多(如不能修改列数据类型等)。####修改表名```sqlALTERTABLEold_table_nameRENAMETOnew_table_name;```####修改列```sqlALTERTABLEtable_nameCHANGE[COLUMN]old_col_namenew_col_namedata_type[COMMENTcol_comment][FIRST|AFTERcolumn_name];```####添加列```sqlALTERTABLEtable_nameADDCOLUMNS(new_col_namedata_type[COMMENTcol_comment],...);```####添加分区```sqlALTERTABLEtable_nameADDPARTITION(partition_col=value,...)[LOCATION'location_path'];```###4.其他数据定义操作-视图:Hive支持创建视图,但视图是只读的。-索引:Hive早期版本支持索引,但在后续版本中已被弃用(引用[1]提到Hive不支持索引)。###总结HiveQL的数据定义语言(DDL)与SQL类似,但具有一些特定的扩展(如分区、分桶、外部表)和限制(如不支持事务、索引)。这些设计是为了适应Hadoop分布式文件系统的大数据处理特性。§§相关问题§§1.HiveQL中内部表和外部表的主要区别是什么?2.如何创建分区表?分区表有什么优势?3.HiveQL支持哪些数据存储格式?4.HiveQL中如何修改表结构?5.HiveQL的数据库属性(DBPROPERTIES)有什么作用?</think>### HiveQL 数据定义语法与功能详解 HiveQL 的数据定义语言(DDL)用于创建、修改和删除数据库对象(如数据库、表、视图等),其语法与 SQL 类似但存在 Hadoop 生态特有的扩展和限制。以下是核心语法和功能: --- #### **1. 数据库操作** **语法:** ```sql CREATE DATABASE [IF NOT EXISTS] db_name [COMMENT 'description'] [LOCATION 'hdfs_path'] [WITH DBPROPERTIES ('key'='value')]; ``` **功能说明:** - `IF NOT EXISTS`:避免重复创建 - `COMMENT`:添加数据库描述(引用[3]) - `LOCATION`:指定 HDFS 存储路径(默认:`/user/hive/warehouse`) - `WITH DBPROPERTIES`:添加自定义元数据键值对(引用[3]) **示例:** ```sql CREATE DATABASE sales_db COMMENT '销售数据集' WITH DBPROPERTIES ('creator'='admin', 'date'='2023-10-01'); ``` --- #### **2. 表操作** ##### **创建表** **基本语法:** ```sql CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name ( column1 data_type [COMMENT '列注释'], ... ) [COMMENT '表注释'] [PARTITIONED BY (partition_column data_type, ...)] -- 分区 [CLUSTERED BY (column) INTO num_buckets BUCKETS] -- 分桶 [ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'] -- 指定数据格式 [STORED AS file_format] -- 文件格式(TEXTFILE, ORC等) [LOCATION 'hdfs_path'] -- 外部表必须指定(引用[4]) [TBLPROPERTIES ('key'='value')]; ``` **核心功能:** - **`EXTERNAL`**:创建外部表(仅管理元数据,删除表时不删除数据) - **分区(`PARTITIONED BY`)**:将数据按分区列物理分割,加速查询 - **分桶(`CLUSTERED BY`)**:哈希分桶优化 JOIN 和采样 - **数据格式控制**: - `ROW FORMAT`:定义行列分隔符(引用[4]) - `STORED AS`:指定文件格式(默认 TEXTFILE) - **`LOCATION`**:自定义 HDFS 存储路径(对 EXTERNAL 表必需) **示例(外部表):** ```sql CREATE EXTERNAL TABLE IF NOT EXISTS user_logs ( user_id INT, action STRING, timestamp BIGINT ) PARTITIONED BY (dt STRING) -- 按日期分区 ROW FORMAT DELIMITED FIELDS TERMINATED BY '|' LOCATION '/data/user_logs'; -- 引用[4]模式 ``` ##### **修改表** **常用操作:** ```sql -- 添加分区 ALTER TABLE table_name ADD PARTITION (dt='2023-10-01'); -- 重命名表 ALTER TABLE old_name RENAME TO new_name; -- 修改列类型 ALTER TABLE table_name CHANGE COLUMN user_id uid STRING; ``` ##### **删除表** ```sql DROP TABLE [IF EXISTS] table_name; -- 内部表:删除元数据+数据 DROP TABLE external_table_name; -- 外部表:仅删除元数据 ``` --- #### **3. 视图操作** **语法:** ```sql CREATE VIEW view_name AS SELECT ... FROM ... WHERE ...; ``` **限制:** - Hive 视图是逻辑对象(不存储数据) - **不支持物化视图** - 视图查询最终转换为底层表查询 --- #### **4. HiveQL DDL 特性总结** | 功能 | 支持情况 | 说明 | |---------------------|----------------------------------|------------------------------------------| | **数据库/表创建** | ✅ 完整支持 | 含分区、分桶、自定义存储格式 | | **数据更新** | ❌ 不支持 | 无法 UPDATE/DELETE 单行数据(引用[1][2])| | **事务** | ❌ 不支持 | 无 ACID 特性(引用[1]) | | **索引** | ❌ 不支持 | 依赖 HDFS 全表扫描(引用[1]) | | **外部表** | ✅ 完整支持 | 数据与元数据解耦(引用[4]) | | **存储格式扩展** | ✅ 支持 ORC/Parquet 等 | 优化压缩和查询性能 | > **关键限制**:HiveQL DDL 设计目标是大规模**批量数据加载**(非实时更新),因此舍弃了事务和索引,但通过分区/分桶实现了查询优化(引用[1][2])。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值