hive和spark读写分区表NULL列
先创建一张非分区表 non_partitioned_table
,并插入10条数据,其中部分 city
和 gender
字段为空。随后我们基于这些数据创建写入分区表。
1. 创建非分区表
首先,创建一张非分区表 non_partitioned_table
,包含所有所需的字段:
CREATE TABLE non_partitioned_table (
name STRING,
age INT,
address STRING,
mobile STRING,
city STRING,
gender STRING,
year INT,
month INT,
date2 DATE,
email STRING
)
STORED AS TEXTFILE; -- 或者可以选择其他存储格式,如 ORC, Parquet 等
2. 插入数据
接下来,向这张表中插入10条数据,其中部分 city
和 gender
字段为空:
INSERT INTO non_partitioned_table (name, age, address, mobile, city, gender, year, month, date2, email) VALUES
('Alice', 30, 'New York', '123456789', 'New York', 'Female', 2024, 1, '2024-01-01', 'alice@example.com'),
('Bob', 25, 'Los Angeles', '987654321', 'Los Angeles', 'Male', 2024, 2, '2024-02-01', 'bob@example.com'),
('Charlie', 35, 'Chicago', '111222333', NULL, 'Male', 2024, 3, '2024-03-01', 'charlie@example.com'),
('Diana', 28, 'Houston', '444555666', 'Houston', NULL, 2024, 4, '2024-04-01', 'diana@example.com'),
('Eve', 22, 'Miami', '777888999', 'Miami', 'Female', 2024, 5, '2024-05-01', 'eve@example.com'),
('Frank', 31, 'Seattle', '123456789', NULL, 'Male', 2024, 6, '2024-06-01', 'frank@example.com'),
('Grace', 27, 'San Francisco', '987654321', 'San Francisco', NULL, 2024, 7, '2024-07-01', 'grace@example.com'),
('Henry', 33, 'Boston', '111222333', 'Boston', 'Male', 2024, 8, '2024-08-01', 'henry@example.com'),
('Ivy', 29, 'Denver', '444555666', NULL, 'Female', 2024, 9, '2024-09-01', 'ivy@example.com'),
('Jack', 26, 'Phoenix', '777888999', 'Phoenix', NULL, 2024, 10, '2024-10-01', 'jack@example.com');
解释
- 表结构:创建了一张名为
non_partitioned_table
的表,包含name
,age
,address
,mobile
,city
,gender
,year
,month
,date
,email
这些字段。 - 插入数据:使用
INSERT INTO
语句一次性插入10条数据。部分记录的city
和gender
字段被设置为NULL
。
验证数据
你可以通过查询表来验证数据是否正确插入:
SELECT * FROM non_partitioned_table;
这会返回表中的所有记录。接下来,我们创建一个分区表并将这些数据从非分区表中导入到分区表中。
3. 创建分区表
首先,创建一个新的分区表 partitioned_table
,并指定分区字段和表格式为 ORC:
CREATE TABLE partitioned_table (
name STRING,
age INT,
address STRING,
mobile STRING,
date2 DATE,
email STRING
)
PARTITIONED BY (
city STRING,
gender STRING,
year INT,
month INT
)
STORED AS ORC;
4. 设置动态分区参数
启用动态分区并设置模式为 nonstrict
:
SET hive.exec.dynamic.partition=true; -- 启用动态分区
SET hive.exec.dynamic.partition.mode=nonstrict; -- 允许在不指定所有分区字段的情况下进行动态分区
5. 插入数据
从 non_partitioned_table
中选择数据并插入到 partitioned_table
中,不处理 NULL
值:
INSERT INTO partitioned_table PARTITION (city, gender, year, month)
SELECT
name,
age,
address,
mobile,
date2,
email,
city,
gender,
year,
month
FROM non_partitioned_table;
解释
- 表结构:创建了一张名为
partitioned_table
的表,包含name
,age
,address
,mobile
,date
,email
这些字段,并且有四个分区字段city
,gender
,year
,month
。 - 动态分区:通过设置
hive.exec.dynamic.partition
和hive.exec.dynamic.partition.mode
参数,启用了动态分区功能。 - 插入数据:使用
INSERT INTO
语句从non_partitioned_table
中选择数据并插入到partitioned_table
中。分区字段city
,gender
,year
,month
在SELECT
子句中被选中,Hive 将根据这些字段的值自动创建和写入分区。
验证数据
你可以通过查询表来验证数据是否正确插入:
SELECT * FROM partitioned_table;
这将返回表中的所有记录,确保数据已正确插入并分区。
6.Hive查询特定分区的数据
如果你想查询 city
或 gender
为 NULL
的数据,可使用如下查询:
-- 查询 city 为 NULL 的数据
SELECT * FROM partitioned_table WHERE city = '__HIVE_DEFAULT_PARTITION__';
-- 查询 gender 为 NULL 的数据
SELECT * FROM partitioned_table WHERE gender = '__HIVE_DEFAULT_PARTITION__';
7.Spark-SQL查询hive分区表
分区字段为空的查询(有效的):
spark-sql --conf spark.sql.hive.convertMetastoreOrc=true -e "SELECT * FROM partitioned_table WHERE city is NULL;"
## spark3则不管这个参数如何设置都可以
spark3-sql --conf spark.sql.hive.convertMetastoreOrc=false -e "SELECT * FROM partitioned_table WHERE city is NULL"
以下这些都不可以(查不到数据):
spark-sql --conf spark.sql.hive.convertMetastoreOrc=false --conf spark.sql.orc.impl=hive --conf spark.sql.orc.filterPushdown=false -e "SELECT * FROM partitioned_table WHERE city = '__HIVE_DEFAULT_PARTITION__';"
spark-sql --conf spark.sql.hive.convertMetastoreOrc=false --conf spark.sql.orc.impl=hive --conf spark.sql.orc.filterPushdown=false -e "SELECT * FROM partitioned_table WHERE city is NULL"
spark-sql --conf spark.sql.hive.convertMetastoreOrc=false -e "SELECT * FROM partitioned_table WHERE city is NULL;"
spark-sql --conf spark.sql.hive.convertMetastoreOrc=false --conf spark.sql.orc.impl=hive --conf spark.sql.hive.optimize.ppd.storage=false -e "SELECT * FROM partitioned_table WHERE city = '__HIVE_DEFAULT_PARTITION__';"
spark3-sql --conf spark.sql.hive.convertMetastoreOrc=false --conf spark.sql.orc.impl=hive -e "SELECT * FROM partitioned_table WHERE city = '__HIVE_DEFAULT_PARTITION__';"