0
# Partition Management
1
2
Partition management provides operations for adding, renaming, and managing Hive table partitions.
3
4
## Capabilities
5
6
### Add Partitions
7
8
Add new partitions to an existing Hive table with optional location specifications.
9
10
```java { .api }
11
/**
12
* ADD PARTITION statement for Hive tables
13
* Adds one or more partitions to an existing partitioned table
14
*/
15
public class SqlAddHivePartitions extends SqlCall {
16
/**
17
* Creates add partitions statement
18
* @param pos Parser position information
19
* @param tableName Name of the table to add partitions to
20
* @param ifNotExists Whether to use IF NOT EXISTS clause
21
* @param partSpecs List of partition specifications
22
* @param partLocations List of partition locations (can be null)
23
*/
24
public SqlAddHivePartitions(SqlParserPos pos, SqlIdentifier tableName, boolean ifNotExists,
25
List<SqlNodeList> partSpecs, List<SqlCharStringLiteral> partLocations);
26
}
27
```
28
29
**Usage Examples:**
30
31
```java
32
// Add single partition
33
String addPartitionSql = """
34
ALTER TABLE sales_data
35
ADD PARTITION (year=2023, month=12)
36
""";
37
38
// Add partition with location
39
String addPartitionWithLocationSql = """
40
ALTER TABLE sales_data
41
ADD PARTITION (year=2023, month=12)
42
LOCATION '/data/sales/2023/12'
43
""";
44
45
// Add multiple partitions
46
String addMultiplePartitionsSql = """
47
ALTER TABLE sales_data
48
ADD IF NOT EXISTS
49
PARTITION (year=2023, month=11) LOCATION '/data/sales/2023/11'
50
PARTITION (year=2023, month=12) LOCATION '/data/sales/2023/12'
51
PARTITION (year=2024, month=1) LOCATION '/data/sales/2024/01'
52
""";
53
54
// Programmatic partition addition
55
SqlIdentifier tableName = new SqlIdentifier("analytics_data", SqlParserPos.ZERO);
56
57
// First partition specification: (date_partition='2023-12-01')
58
SqlNodeList partSpec1 = new SqlNodeList(SqlParserPos.ZERO);
59
partSpec1.add(new SqlTableOption("date_partition", "2023-12-01", SqlParserPos.ZERO));
60
61
// Second partition specification: (date_partition='2023-12-02')
62
SqlNodeList partSpec2 = new SqlNodeList(SqlParserPos.ZERO);
63
partSpec2.add(new SqlTableOption("date_partition", "2023-12-02", SqlParserPos.ZERO));
64
65
List<SqlNodeList> partSpecs = List.of(partSpec1, partSpec2);
66
List<SqlCharStringLiteral> locations = List.of(
67
SqlLiteral.createCharString("/data/analytics/2023-12-01", SqlParserPos.ZERO),
68
SqlLiteral.createCharString("/data/analytics/2023-12-02", SqlParserPos.ZERO)
69
);
70
71
SqlAddHivePartitions addPartitions = new SqlAddHivePartitions(
72
SqlParserPos.ZERO,
73
tableName,
74
true, // IF NOT EXISTS
75
partSpecs,
76
locations
77
);
78
```
79
80
### Rename Partitions
81
82
Rename existing partitions by changing their partition values.
83
84
```java { .api }
85
/**
86
* PARTITION RENAME statement for Hive tables
87
* Renames an existing partition by changing its partition specification
88
*/
89
public class SqlAlterHivePartitionRename extends SqlAlterHiveTable {
90
/**
91
* Creates partition rename statement
92
* @param pos Parser position information
93
* @param tableName Name of table containing the partition
94
* @param partSpec Current partition specification
95
* @param newPartSpec New partition specification
96
* @throws ParseException if validation fails
97
*/
98
public SqlAlterHivePartitionRename(SqlParserPos pos, SqlIdentifier tableName,
99
SqlNodeList partSpec, SqlNodeList newPartSpec) throws ParseException;
100
101
/**
102
* Gets the new partition specification
103
* @return SqlNodeList containing new partition values
104
*/
105
public SqlNodeList getNewPartSpec();
106
}
107
```
108
109
**Usage Examples:**
110
111
```java
112
// Rename partition
113
String renamePartitionSql = """
114
ALTER TABLE sales_data
115
PARTITION (year=2023, month=13)
116
RENAME TO PARTITION (year=2024, month=1)
117
""";
118
119
// Programmatic partition rename
120
SqlIdentifier tableName = new SqlIdentifier("sales_data", SqlParserPos.ZERO);
121
122
// Current partition specification
123
SqlNodeList currentPartSpec = new SqlNodeList(SqlParserPos.ZERO);
124
currentPartSpec.add(new SqlTableOption("year", "2023", SqlParserPos.ZERO));
125
currentPartSpec.add(new SqlTableOption("month", "13", SqlParserPos.ZERO));
126
127
// New partition specification
128
SqlNodeList newPartSpec = new SqlNodeList(SqlParserPos.ZERO);
129
newPartSpec.add(new SqlTableOption("year", "2024", SqlParserPos.ZERO));
130
newPartSpec.add(new SqlTableOption("month", "1", SqlParserPos.ZERO));
131
132
SqlAlterHivePartitionRename renamePartition = new SqlAlterHivePartitionRename(
133
SqlParserPos.ZERO,
134
tableName,
135
currentPartSpec,
136
newPartSpec
137
);
138
139
// Access new partition specification
140
SqlNodeList newSpec = renamePartition.getNewPartSpec();
141
```
142
143
### Partition Operations in Table Alterations
144
145
Many table alteration operations can be applied to specific partitions:
146
147
```java
148
// Change partition location
149
String changePartLocationSql = """
150
ALTER TABLE sales_data
151
PARTITION (year=2023, month=12)
152
SET LOCATION '/new/data/sales/2023/12'
153
""";
154
155
// Change partition file format
156
String changePartFormatSql = """
157
ALTER TABLE sales_data
158
PARTITION (year=2023, month=12)
159
SET FILEFORMAT PARQUET
160
""";
161
162
// Change partition SerDe
163
String changePartSerdeSql = """
164
ALTER TABLE sales_data
165
PARTITION (year=2023, month=12)
166
SET SERDE 'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
167
WITH SERDEPROPERTIES (
168
'serialization.format' = '1'
169
)
170
""";
171
```
172
173
## Advanced Partition Management
174
175
### Dynamic Partition Creation
176
177
Partitions are often created dynamically during INSERT operations:
178
179
```java
180
// Dynamic partition insert
181
String dynamicInsertSql = """
182
INSERT INTO TABLE sales_data
183
PARTITION (year, month)
184
SELECT id, customer_id, product_name, amount, transaction_date,
185
YEAR(transaction_date) as year,
186
MONTH(transaction_date) as month
187
FROM raw_sales_data
188
""";
189
```
190
191
### Partition Validation
192
193
Partition specifications are validated during parsing:
194
195
```java
196
try {
197
// This will validate partition column types and values
198
SqlAddHivePartitions addPartitions = new SqlAddHivePartitions(
199
pos, tableName, false, partSpecs, locations
200
);
201
} catch (ParseException e) {
202
// Thrown for invalid partition specifications
203
System.err.println("Invalid partition specification: " + e.getMessage());
204
}
205
```
206
207
### Partition Specification Format
208
209
Partition specifications follow specific format requirements:
210
211
```java
212
// Valid partition specifications
213
String validPartitions = """
214
PARTITION (year=2023, month=12, day=15) -- Multiple columns
215
PARTITION (date_str='2023-12-15') -- String partition
216
PARTITION (year=2023) -- Single column
217
""";
218
219
// Partition specification building
220
SqlNodeList buildPartitionSpec(Map<String, String> partitionValues) {
221
SqlNodeList partSpec = new SqlNodeList(SqlParserPos.ZERO);
222
223
for (Map.Entry<String, String> entry : partitionValues.entrySet()) {
224
partSpec.add(new SqlTableOption(
225
entry.getKey(),
226
entry.getValue(),
227
SqlParserPos.ZERO
228
));
229
}
230
231
return partSpec;
232
}
233
234
// Usage
235
Map<String, String> partValues = Map.of(
236
"year", "2023",
237
"month", "12",
238
"region", "us-west"
239
);
240
SqlNodeList partSpec = buildPartitionSpec(partValues);
241
```
242
243
### Complete Partition Management Example
244
245
```java
246
public class PartitionManager {
247
private SqlParser parser;
248
private TableEnvironment tableEnv;
249
250
public PartitionManager(TableEnvironment tableEnv) {
251
this.tableEnv = tableEnv;
252
this.parser = SqlParser.create("",
253
SqlParser.config().withParserFactory(FlinkHiveSqlParserImpl.FACTORY));
254
}
255
256
public void addMonthlyPartitions(String tableName, int year, int[] months) {
257
for (int month : months) {
258
String addPartitionSql = String.format("""
259
ALTER TABLE %s
260
ADD IF NOT EXISTS PARTITION (year=%d, month=%d)
261
LOCATION '/data/%s/%d/%02d'
262
""", tableName, year, month, tableName, year, month);
263
264
try {
265
tableEnv.executeSql(addPartitionSql);
266
System.out.println("Added partition: year=" + year + ", month=" + month);
267
} catch (Exception e) {
268
System.err.println("Failed to add partition: " + e.getMessage());
269
}
270
}
271
}
272
273
public void reorganizePartition(String tableName, String oldYearMonth, String newYearMonth) {
274
// Step 1: Add new partition
275
String[] oldParts = oldYearMonth.split("-");
276
String[] newParts = newYearMonth.split("-");
277
278
String addNewPartitionSql = String.format("""
279
ALTER TABLE %s
280
ADD IF NOT EXISTS PARTITION (year=%s, month=%s)
281
""", tableName, newParts[0], newParts[1]);
282
283
// Step 2: Move data (would be done outside parser, e.g., with INSERT INTO ... SELECT)
284
285
// Step 3: Drop old partition (would use DROP PARTITION statement)
286
287
try {
288
tableEnv.executeSql(addNewPartitionSql);
289
System.out.println("Reorganized partition from " + oldYearMonth + " to " + newYearMonth);
290
} catch (Exception e) {
291
System.err.println("Failed to reorganize partition: " + e.getMessage());
292
}
293
}
294
295
public void updatePartitionLocation(String tableName, Map<String, String> partitionSpec, String newLocation) {
296
StringBuilder partSpecSql = new StringBuilder("PARTITION (");
297
partitionSpec.entrySet().stream()
298
.map(entry -> entry.getKey() + "=" + entry.getValue())
299
.collect(joining(", "));
300
partSpecSql.append(")");
301
302
String updateLocationSql = String.format("""
303
ALTER TABLE %s
304
%s
305
SET LOCATION '%s'
306
""", tableName, partSpecSql.toString(), newLocation);
307
308
try {
309
tableEnv.executeSql(updateLocationSql);
310
System.out.println("Updated partition location: " + newLocation);
311
} catch (Exception e) {
312
System.err.println("Failed to update partition location: " + e.getMessage());
313
}
314
}
315
}
316
317
// Usage
318
PartitionManager partManager = new PartitionManager(tableEnv);
319
320
// Add quarterly partitions
321
partManager.addMonthlyPartitions("sales_data", 2024, new int[]{1, 2, 3});
322
323
// Reorganize misnamed partition
324
partManager.reorganizePartition("sales_data", "2023-13", "2024-1");
325
326
// Update partition location
327
Map<String, String> partSpec = Map.of("year", "2023", "month", "12");
328
partManager.updatePartitionLocation("sales_data", partSpec, "/data/archived/sales/2023/12");
329
```