A technical troubleshooting blog about Oracle with other Databases & Cloud Technologies.

Hash partitioning in Oracle !!

3 min read

Hash partitioning is a database partitioning technique used in Oracle databases to distribute data evenly across multiple partitions. This method is particularly useful for ensuring a balanced distribution of data and for improving query performance by minimizing data retrieval times.

In contrast to Range or List Partitioning, where you specify the criteria that determine the partition a row belongs to based on the value in the partition key column(s), Hash Partitioning takes a different approach. With Hash Partitioning, Oracle applies a hashing algorithm to distribute rows “randomly” across the available partitions in the table.

This method is particularly useful when the goal is to divide a table into smaller physical segments (potentially located in different tablespaces on separate disks) without needing to group the data in any particular way.

How Hash Partitioning Works

Partition Key: A hash function is applied to a specified partition key column. The hash function determines the partition into which a given row should be placed.

Hash Function: Oracle uses an internal hash function to map the partition key values to specific partitions. The goal is to distribute rows evenly across all partitions.

Partitions: The result of the hash function determines the partition number. For example, if there are 4 partitions and the hash function results in a value between 0 and 3, the row will be placed in the corresponding partition.

Benefits of Hash Partitioning

Load Balancing: Even distribution of data across partitions helps in avoiding hotspots and ensures balanced workload.

Improved Performance: Since data is evenly distributed, parallel queries can be more efficient, leading to better performance for read and write operations.

Simplified Management: Unlike range partitioning, hash partitioning does not require constant monitoring and management of partition boundaries.

    Create 4 Tablespace corresponding to 4 partition.

    CREATE TABLESPACE hash_part1
    DATAFILE '/u01/app/oracle/oradata/PROD101/hash_part1.dbf' SIZE 100M
    AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL
    SEGMENT SPACE MANAGEMENT AUTO;
    
    CREATE TABLESPACE hash_part2
    DATAFILE '/u01/app/oracle/oradata/PROD101/hash_part2.dbf' SIZE 100M
    AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL
    SEGMENT SPACE MANAGEMENT AUTO;
    
    CREATE TABLESPACE hash_part3
    DATAFILE '/u01/app/oracle/oradata/PROD101/hash_part3.dbf' SIZE 100M
    AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL
    SEGMENT SPACE MANAGEMENT AUTO;
    
    CREATE TABLESPACE hash_part4
    DATAFILE '/u01/app/oracle/oradata/PROD101/hash_part4.dbf' SIZE 100M
    AUTOEXTEND ON NEXT 10M MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL
    SEGMENT SPACE MANAGEMENT AUTO;
    

    Create 4 Partitions in 4 different Tablespaces:

    SQL>  create table table_for_partition
      (Sl_number number,
       Sl_key varchar2(32),
       product_value varchar2(64),
       product_timestamp timestamp)
      partition by hash (Sl_number)
      (partition p1 tablespace hash_part1,
       partition p2 tablespace hash_part2,
       partition p3 tablespace hash_part3,
       partition p4 tablespace hash_part4)
      /
    
    Table created.
    

    Insert 10,000 rows from a single session in Partition table:

    SQL> insert into table_for_partition
     select rownum,                               
     dbms_random.string('X',16),
     dbms_random.string('X',32),
     systimestamp
     from dual
     connect by level < 10001;   
    
    10000 rows created.
    
    
    SQL> commit;
    Commit complete.
    
    

    Gather Table Statistics:

    SQL> exec dbms_stats.gather_table_stats('SYS','table_for_partition');
    
    PL/SQL procedure successfully completed.
    
    SQL> 
    

    Validate the outputs:

    Select random rows from the Partition Table:

    SQL> select partition_name, num_rows
    from dba_tab_partitions
    where table_name = 'TABLE_FOR_PARTITION'
    order by partition_position;
    
    PARTITION_NAME	  NUM_ROWS
    --------------- ----------
    P1			   2471
    P2			   2527
    P3			   2521
    P4			   2481
    
    
    SQL> select Sl_number  
    from table_for_partition partition (P1)
    where rownum < 10
    order by 1; 
    
     SL_NUMBER
    ----------
          4577
          4580
          4582
          4586
          4596
          4601
          4603
          4604
          4605
    
    9 rows selected.
    
    SQL> select Sl_number
     from table_for_partition partition (P2)
     where rownum < 10
     order by 1;
    
     SL_NUMBER
    ----------
          4519
          4522
          4528
          4529
          4537
          4539
          4540
          4544
          4546
    
    9 rows selected.
    
    SQL> select Sl_number
    from table_for_partition partition (P3)
    where rownum < 10
    and Sl_number < 100
    order by 1;
      
     SL_NUMBER
    ----------
    	 2
    	 5
    	 8
    	18
    	20
    	21
    	23
    	24
    	33
    
    9 rows selected.
    
    SQL> select Sl_number
    from table_for_partition partition (P4)
    where rownum < 10
    and Sl_number between 700 and 1000
    order by 1;
    
     SL_NUMBER
    ----------
           709
           711
           716
           721
           729
           732
           736
           737
           739
    
    9 rows selected.
    
    

    Hope it helped !! 🙂