Search code examples
mysqlsqlpartitioningunique-constraintdata-partitioning

How do you specify multiple columns for the key, as part of a hash subpartition?


I'm creating a table with composite partitioning (RANGE, then HASH)

My actual table is enormous, so here's a stripped down dummy table that shows the important parts:

CREATE TABLE table1(
    id INT NOT NULL AUTO_INCREMENT,

    dtvalue DATETIME NOT NULL, -- Used for RANGE partitions

    v1 INT NOT NULL, -- Used for HASH partitions
    v2 INT NOT NULL,

    CONSTRAINT pk_table1 PRIMARY KEY(id),

    CONSTRAINT uk_table1 UNIQUE(v1,v2) -- Unique key for v1 and v2
)
ROW_FORMAT=COMPRESSED
PARTITION BY RANGE(dtvalue)
SUBPARTITION BY HASH(v1,v2) SUBPARTITIONS 32 -- Does this HASH subpartition work?
(PARTITION p20191101 VALUES LESS THAN('2019-11-01'),
 PARTITION p20191102 VALUES LESS THAN('2019-11-02'),
 PARTITION pMax VALUES LESS THAN MAXVALUE);

This table will frequently be joined by v1 and v2 combined as a unique identifier, so using both columns for the HASH key is critical.

My question is, can you specify multiple columns as part of the HASH key?

Or can you specify the unique key itself, for the HASH key?
e.g. SUBPARTITION BY HASH(uk_table1) SUBPARTITIONS 32


Solution

  • You may want to rethink your approach concerning partitioning. MySQL is quite finicky -- so primary keys and unique constraints need to include the partitioning keys.

    And, the hash partitioning takes an integer, but has a very limited repertoire of allowed explicit functions. Happily, you can get around that with a stored generated column.

    So, the following accomplishes your stated goal:

    CREATE TABLE table1 (
        id INT NOT NULL AUTO_INCREMENT,
    
        dtvalue datetime NOT NULL, -- Used for RANGE partitions
    
        v1 INT NOT NULL, -- Used for HASH partitions
        v2 INT NOT NULL,
    
        CONSTRAINT pk_table1 PRIMARY KEY(id, dtvalue, v1_v2),
    
        v1_v2 int generated always as (cast(conv(left(md5(concat_ws(':', v1, v2)), 8), 16, 10) as unsigned)) stored
    )
    ROW_FORMAT=COMPRESSED
    PARTITION BY RANGE COLUMNS (dtvalue)
    SUBPARTITION BY HASH (v1_v2) SUBPARTITIONS 32 -- Does this HASH subpartition work?
    (PARTITION p20191101 VALUES LESS THAN ('2019-11-01'),
     PARTITION p20191102 VALUES LESS THAN ('2019-11-02'),
     PARTITION pMax VALUES LESS THAN MAXVALUE);