Hive Partitions & Buckets with Example

⚡ Smart Summary

Partitions and buckets are the two ways Apache Hive splits table data on disk: a partition creates one directory per key value, while a bucket hashes rows into a fixed number of files.

  • 🗂️ Partition is a directory: Each distinct value of the partition key becomes its own subdirectory under the table folder in HDFS.
  • ✂️ Partition pruning: A query that filters on the partition key reads only the matching directories instead of scanning the whole table.
  • ⚙️ Dynamic mode required: Loading many partitions from a SELECT needs hive.exec.dynamic.partition.mode set to nonstrict.
  • 🧮 Bucket is a file: CLUSTERED BY hashes the chosen column and writes each row into one of a fixed number of files.
  • 🔍 Sampling and joins: Bucketed tables support efficient TABLESAMPLE reads and map-side bucket joins that plain tables cannot.
  • 📐 Choose by cardinality: Partition on low-cardinality columns such as state or date, and bucket high-cardinality columns such as user identifiers.

Hive partitions and buckets explained with a worked example

Tables, Partitions, and Buckets are the parts of Hive data modeling. A table defines the schema, a partition splits that table into directories on disk, and a bucket splits the data inside a directory into a fixed number of files.

What is Partitions?

Hive Partitions is a way to organizes tables into partitions by dividing tables into different parts based on partition keys. Physically, every partition is a separate subdirectory under the table folder in HDFS, which is what allows Hive to skip data it does not need.

Partition is helpful when the table has one or more Partition keys. Partition keys are basic elements for determining how the data is stored in the table. A partition key is not stored inside the data files themselves – its value is encoded in the directory name, so a query filtering on that key can discard whole directories before any row is read. This is called partition pruning.

For Example: –

“Client having Some E–commerce data which belongs to India operations in which each state (38 states) operations mentioned in as a whole. If we take state column as partition key and perform partitions on that India data as a whole, we can able to get Number of partitions (38 partitions) which is equal to number of states (38) present in India. Such that each state data can be viewed separately in partitions tables.”

Sample Code Snippet for partitions

The six statements below run in order in the Hive shell. Each one is a separate step, and the screenshots that follow show the same sequence executing on a live cluster.

  1. Creation of table allstates
    create table allstates(state string, District string,Enrolments string)
    
    row format delimited
    
    fields terminated by ',';
    
  2. Loading data into created table allstates
    Load data local inpath '/home/hduser/Desktop/AllStates.csv' into table allstates;
  3. Creation of partition table
    create table state_part(District string,Enrolments string) PARTITIONED BY(state string);
  4. For partition we have to set this property
    set hive.exec.dynamic.partition.mode=nonstrict
  5. Loading data into partition table
    INSERT OVERWRITE TABLE state_part PARTITION(state)
    SELECT district,enrolments,state from  allstates;
  6. Actual processing and formation of partition tables based on state as partition key

There are going to be 38 partition outputs in HDFS storage with the file name as state name. We will check this in this step.

The following screen shots show the execution of the above mentioned code.

In the first screen, step 1 runs at the hive> prompt and creates the allstates table with its three columns and a comma as the field delimiter.

Hive shell creating the allstates table with three delimited columns

The next screen covers steps 2 and 3: the AllStates.csv file is loaded into allstates, and the partitioned table state_part is created with state declared as the partition key.

Loading AllStates.csv into allstates and creating the partitioned table state_part

Steps 4 and 5 appear next. Dynamic partition mode is set to nonstrict, and the INSERT OVERWRITE statement launches a MapReduce job whose log lines show one partition being loaded for each state value.

MapReduce job output loading one Hive partition per state value

Listing the warehouse directory in HDFS confirms the result of step 6 – the shell reports 38 items, one state_part/state= directory per state.

HDFS listing showing 38 state_part partition directories in the Hive warehouse

From the above code, we do following things

  1. Creation of table allstates with 3 column names such as state, district, and enrolments
  2. Loading data into table allstates
  3. Creation of partition table with state as partition key
  4. In this step setting partition mode as non-strict (this mode will activate dynamic partition mode)
  5. Loading data into partition table state_part
  6. Actual processing and formation of partition tables based on state as partition key
  7. There are going to be 38 partition outputs in HDFS storage with the file name as state name. In this step, we see the 38 partition outputs in HDFS

Static vs Dynamic Partitioning in Hive

The worked example above uses dynamic partitioning, but Hive supports two loading styles and the difference decides how much typing – and how much risk – each load carries.

Static partitioning names the partition value in the statement itself, so the value must be known before the load runs and one statement fills exactly one partition. Dynamic partitioning lets Hive read the partition value out of the last column of the SELECT list and create the directories at runtime, which is why the example needs only a single INSERT to produce 38 directories.

Aspect Static partitioning Dynamic partitioning
Partition value Supplied by hand in the PARTITION clause Read at runtime from the SELECT column
Partitions per statement One Many
Configuration Works in the default strict mode Needs hive.exec.dynamic.partition.mode set to nonstrict
Load speed Faster, because no value scan is needed Slower, because the job groups rows by key
Best suited to Small, known sets such as a daily load Large or unknown key sets such as 38 states

Dynamic loads are also capped. Hive limits how many partitions one job may create – by default 100 per mapper or reducer and 1000 for the whole statement – and the job fails once either ceiling is crossed, so a very high-cardinality key needs those limits raised or a different design.

What is Buckets?

Buckets in Hive are used in segregating of Hive table-data into multiple files or directories. They are used for efficient querying, and unlike a partition the number of buckets is fixed when the table is created, so it never grows with the data.

  • The data that is present in those partitions can be divided further into buckets
  • The division is performed based on hash of particular columns that we selected in the table
  • Buckets use some form of hashing algorithm at back end to read each record and place it into buckets
  • The bucket a row lands in is decided by hash_function(bucketing_column) mod num_buckets, so equal values always land in the same file
  • On Hive 0.x and 1.x, bucketing had to be enabled with set hive.enforce.bucketing=true; before the insert

That last setting is history on a current cluster: the Apache Hive manual notes it is not needed from Hive 2.x onward, because the engine now picks the reducer count and cluster-by column from the table definition automatically.

Step 1) Creating Bucket as shown below.

The screen below shows the CREATE TABLE statement for samplebucket, with the CLUSTERED BY clause at the bottom fixing the bucket count.

Hive CREATE TABLE statement clustering samplebucket into four buckets

From the above screen shot

  • We are creating samplebucket with column names such as first_name, job_id, department, salary and country
  • We are creating 4 buckets over here
  • Once the data gets loaded it automatically places the data into 4 buckets
  • The country column is the clustering column, so every row for one country is written to the same bucket file

Step 2) Loading data into table samplebucket

Assuming that the “employees” table is already created in the Hive system, in this step we will see the loading of data from the employees table into the table samplebucket.

Before we start moving employees data into buckets, make sure that it consists of column names such as first_name, job_id, department, salary and country.

Here we are loading data into samplebucket from the employees table – the screen below shows the INSERT OVERWRITE statement that performs the copy.

INSERT OVERWRITE statement copying employees rows into the samplebucket table

Step 3) Displaying the 4 buckets created in Step 1

Listing the table directory in HDFS shows the physical result: four numbered data files rather than one.

HDFS listing of the four bucket files created under the samplebucket directory

From the above screenshot, we can see that the data from the employees table is transferred into the 4 buckets created in step 1.

Hive Partitioning vs Bucketing: Key Differences

Both features cut a table into smaller pieces, but they do it at different levels of the file system and they answer different problems. The table below sets them side by side.

Point of comparison Partitioning Bucketing
Unit created A directory per key value A file per hash bucket
Declared with PARTITIONED BY CLUSTERED BY … INTO n BUCKETS
Number of pieces Grows with the number of distinct values Fixed at table creation
Column stored in data files No – the value lives in the directory name Yes – the column stays a normal column
Best column type Low cardinality, such as state, year or country High cardinality, such as user_id or transaction_id
Main benefit Partition pruning skips unneeded directories Even file sizes, cheap sampling and map-side joins

The two are not rivals. A common production layout partitions a fact table by date and then buckets each day on the join key, so a query prunes to one directory and then joins bucket-to-bucket inside it.

When to Use Partitioning, Bucketing, or Both

Choosing between them starts with the cardinality of the column and the shape of the queries that will read the table.

  • Partition when queries almost always filter on the same low-cardinality column, and when the number of distinct values stays in the hundreds rather than the millions
  • Bucket when the useful column has too many distinct values to be a directory, or when the table is joined or sampled repeatedly on that column
  • Use both for large fact tables: partition on the date, then bucket inside each partition on the join key

The failure mode to watch for is the small-files problem. Partitioning on a column with very high cardinality – a timestamp or a customer identifier – produces thousands of tiny directories, each holding a file far below the HDFS block size. That inflates NameNode memory and makes every scan slower, which is exactly the outcome partitioning was meant to prevent. Bucketing avoids this because the file count is capped by the table definition.

Bucketing has its own caveat: the layout is only correct if every writer honours it. The bucket count declared at creation is metadata, so a job that writes to the table without clustering correctly can leave files that do not match the declared layout, and later sampling or bucket joins will read the wrong rows.

FAQs

Run SHOW PARTITIONS table_name in the Hive shell. It reads the metastore and prints one line per partition directory, which is faster than listing the warehouse path in HDFS and also confirms the metastore is in sync.

ALTER TABLE table_name ADD PARTITION (state=’Goa’) registers a new directory, and ALTER TABLE table_name DROP PARTITION (state=’Goa’) removes it. Dropping a managed partition deletes its data, while dropping an external one only clears the metastore entry.

Hive caps dynamic partitions at 100 per node and 1000 per statement by default. A key with more distinct values trips the limit and kills the job. Raise hive.exec.max.dynamic.partitions.pernode and hive.exec.max.dynamic.partitions, or pick a coarser key.

No. It was needed on Hive 0.x and 1.x to force the reducer count to match the bucket count. HIVE-12331 removed it in Hive 2.0, and the engine now derives both the reducer count and the cluster-by column from the table.

TABLESAMPLE(BUCKET x OUT OF y ON column) reads only the matching bucket files instead of scanning everything. Because rows were hashed on the same column at write time, the sample is repeatable and far cheaper than a random row filter.

Splitting a table into thousands of tiny files wastes NameNode memory and starts one task per file, so scans slow down. It usually follows a partition key with very high cardinality. Coarser keys, bucketing or file compaction fix it.

Yes. Query-log analysis and machine learning models in tools such as Cloudera Workload XM rank columns by filter frequency, skew and cardinality, then suggest a layout. The suggestion still needs review, because it cannot see planned workloads.

Copilot drafts PARTITIONED BY and CLUSTERED BY statements quickly from a comment, and agentic assistants can generate a whole load script. Always check the generated bucket count and key against real cardinality, because the model guesses from names alone.

Summarize this post with: