Bootstrap

hive和spark读写分区表NULL列

先创建一张非分区表 non_partitioned_table,并插入10条数据,其中部分 citygender 字段为空。随后我们基于这些数据创建写入分区表。

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条数据,其中部分 citygender 字段为空:

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', '[email protected]'),
('Bob', 25, 'Los Angeles', '987654321', 'Los Angeles', 'Male', 2024, 2, '2024-02-01', '[email protected]'),
('Charlie', 35, 'Chicago', '111222333', NULL, 'Male', 2024, 3, '2024-03-01', '[email protected]'),
('Diana', 28, 'Houston', '444555666', 'Houston', NULL, 2024, 4, '2024-04-01', '[email protected]'),
('Eve', 22, 'Miami', '777888999', 'Miami', 'Female', 2024, 5, '2024-05-01', '[email protected]'),
('Frank', 31, 'Seattle', '123456789', NULL, 'Male', 2024, 6, '2024-06-01', '[email protected]'),
('Grace', 27, 'San Francisco', '987654321', 'San Francisco', NULL, 2024, 7, '2024-07-01', '[email protected]'),
('Henry', 33, 'Boston', '111222333', 'Boston', 'Male', 2024, 8, '2024-08-01', '[email protected]'),
('Ivy', 29, 'Denver', '444555666', NULL, 'Female', 2024, 9, '2024-09-01', '[email protected]'),
('Jack', 26, 'Phoenix', '777888999', 'Phoenix', NULL, 2024, 10, '2024-10-01', '[email protected]');
解释
  • 表结构:创建了一张名为 non_partitioned_table 的表,包含 name, age, address, mobile, city, gender, year, month, date, email 这些字段。
  • 插入数据:使用 INSERT INTO 语句一次性插入10条数据。部分记录的 citygender 字段被设置为 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.partitionhive.exec.dynamic.partition.mode 参数,启用了动态分区功能。
  • 插入数据:使用 INSERT INTO 语句从 non_partitioned_table 中选择数据并插入到 partitioned_table 中。分区字段 city, gender, year, monthSELECT 子句中被选中,Hive 将根据这些字段的值自动创建和写入分区。
验证数据

你可以通过查询表来验证数据是否正确插入:

SELECT * FROM partitioned_table;

这将返回表中的所有记录,确保数据已正确插入并分区。

6.Hive查询特定分区的数据

如果你想查询 citygenderNULL 的数据,可使用如下查询:

-- 查询 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__';"
;