You can't use FROM_UNIXTIME() because hash partitions must be based on an integer expression. But assuming your timestamp is stored as an integer, you can use DIV
to return an integer.
Here's a demo of partitioning in the way you describe:
mysql> create table table_to_partition (
my_timestamp int unsigned primary key
) partition by hash(my_timestamp DIV (60*60*24)) partitions 3;
mysql> insert into table_to_partition values (unix_timestamp(now()));
mysql> insert into table_to_partition values (unix_timestamp(now()-interval 1 day));
mysql> insert into table_to_partition values (unix_timestamp(now()-interval 2 day));
mysql> insert into table_to_partition values (unix_timestamp(now()-interval 3 day));
mysql> insert into table_to_partition values (unix_timestamp(now()-interval 4 day));
mysql> insert into table_to_partition values (unix_timestamp(now()-interval 5 day));
mysql> select table_name, partition_name, table_rows
from information_schema.partitions where table_name='table_to_partition';
+--------------------+----------------+------------+
| table_name | partition_name | table_rows |
+--------------------+----------------+------------+
| table_to_partition | p0 | 2 |
| table_to_partition | p1 | 2 |
| table_to_partition | p2 | 2 |
+--------------------+----------------+------------+
I had to do the same thing and solved slightly differently. Basically as far as I understand by reading the docs MySQL subpartitioning does not support partition types besides HASH and KEY.
In MySQL 5.6, it is possible to subpartition tables that are partitioned by RANGE or LIST. Subpartitions may use either HASH or KEY partitioning. This is also known as composite partitioning.
This means that we can't determine in what subpartition a record will end up. It's up to MySQL. So I don't think it's wise giving such names to your subpartitions (i.e. january) because no way you're going to know if stuff created on that month will end up there. This because you can't subpartition by MONTH(nav_date)
but only by HASH(MONTH(nav_date))
or KEY(MONTH(nav_date))
.
So to solve the problem I decided to create a new month
column in my table and then I added an index to it. Then I subpartioned by KEY(month)
without caring about the subpartition names. This way in MySQL 5.6 I could select the main partition from the FROM clause and the subpartition by specifying the month in the WHERE clause.
Follows the full example:
CREATE TABLE `my_example` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`value` double DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`timestamp` datetime NOT NULL,
`last_modified` datetime NOT NULL,
`month` tinyint(1) NOT NULL,
PRIMARY KEY (`id`,`timestamp`, `month`),
KEY `in_is_deleted` (`is_deleted`),
KEY `in_last_modified` (`last_modified`),
KEY `in_timestamp` (`timestamp`),
KEY `in_month` (`month`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
PARTITION BY RANGE (YEAR(`timestamp`))
SUBPARTITION BY KEY (`month`)
SUBPARTITIONS 12 (
PARTITION p2011 VALUES LESS THAN (2012),
PARTITION p2012 VALUES LESS THAN (2013),
PARTITION p2013 VALUES LESS THAN (2014),
PARTITION p2014 VALUES LESS THAN (2015),
PARTITION p2015 VALUES LESS THAN (2016),
PARTITION p2016 VALUES LESS THAN (2017),
PARTITION p2017 VALUES LESS THAN (2018),
PARTITION pmax VALUES LESS THAN MAXVALUE
);
EXPLAIN PARTITIONS SELECT * FROM my_example PARTITION (p2015); -- will go through all twelve subpartitions
EXPLAIN PARTITIONS SELECT * FROM my_example PARTITION (p2015) WHERE month = 9; -- will look only into one subpartition
Best Answer
From here, below is an example that range partitions by
YEAR
- change as appropriate.Here is the part of the manual that explains how to alter tables and add partitions. You should be able to take it from here.