Changing MySQL range partition clause - mysql

I have a table created with range partitioning implemented. The clause is :
...partition by range (DAYOFMONTH(day))
(PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
...
PARTITION p30 VALUES LESS THAN (31)
);
Now, I wish to change the partitioning condition to
.... partition by range (DAYOFMONTH(day) mod 31)
with the rest of individual partition definitions remaining the same. Is it possible to do so by any ALTER TABLE command or do I have to remove partitioning first and recreate partitions with the new condition?
I researched quite a lot about this but all information found was about reorganizing individual partitions.Thank you.

And you are saying following won't work for you ? I tried on version 5.6.10 successfully !
ALTER TABLE table_name
PARTITION BY RANGE( DAYOFMONTH(day) mod 31 ) (
PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (4),
...
PARTITION p30 VALUES LESS THAN (31)
);

Related

How can I partition using a BINARY column in MySQL?

I have so far only found the following very unelegant solution to creating a TABLE with a PARTITION on a BINARY column in MySQL (not part of primary key, so I can't use PARTITION BY KEY):
CREATE TABLE IF NOT EXISTS TestPartition (
uuid BINARY(16) NOT NULL
)
PARTITION BY RANGE COLUMNS(uuid) (
PARTITION p0 VALUES LESS THAN (X'10000000000000000000000000000000'),
PARTITION p1 VALUES LESS THAN (X'20000000000000000000000000000000'),
PARTITION p2 VALUES LESS THAN (X'30000000000000000000000000000000'),
PARTITION p3 VALUES LESS THAN (X'40000000000000000000000000000000'),
PARTITION p4 VALUES LESS THAN (X'50000000000000000000000000000000'),
PARTITION p5 VALUES LESS THAN (X'60000000000000000000000000000000'),
PARTITION p6 VALUES LESS THAN (X'70000000000000000000000000000000'),
PARTITION p7 VALUES LESS THAN (X'80000000000000000000000000000000'),
PARTITION p8 VALUES LESS THAN (X'90000000000000000000000000000000'),
PARTITION p9 VALUES LESS THAN (X'A0000000000000000000000000000000'),
PARTITION pA VALUES LESS THAN (X'B0000000000000000000000000000000'),
PARTITION pB VALUES LESS THAN (X'C0000000000000000000000000000000'),
PARTITION pC VALUES LESS THAN (X'D0000000000000000000000000000000'),
PARTITION pD VALUES LESS THAN (X'E0000000000000000000000000000000'),
PARTITION pE VALUES LESS THAN (X'F0000000000000000000000000000000'),
PARTITION pF VALUES LESS THAN (MAXVALUE)
);
Is there a better way to do this? This becomes unpleasant if I want more partitions.

mysql partition by range performance on a date column

Need advise on partitioning my database tables. The table has 12M rows.
I currently built the following partitions. Resulted in great performance increase on my queries.
ALTER TABLE sales_data_mkt
PARTITION BY RANGE ( TO_DAYS(`ACTIVITY_DT`) ) (
PARTITION p0 VALUES LESS THAN ( TO_DAYS('2015-01-01') ),
PARTITION p1 VALUES LESS THAN ( TO_DAYS('2015-02-01') ),
PARTITION p2 VALUES LESS THAN ( TO_DAYS('2015-03-01') ),
PARTITION p3 VALUES LESS THAN ( TO_DAYS('2015-04-01') ),
PARTITION p4 VALUES LESS THAN ( TO_DAYS('2015-05-01') ),
PARTITION p5 VALUES LESS THAN (MAXVALUE)
);
After doing all this i saw that you can also partition without the To_DAYS() method using Partition by Range columns
ALTER TABLE sales_data_mkt
PARTITION BY RANGE columns (`ACTIVITY_DT`) (
PARTITION p0 VALUES LESS THAN ('2015-01-01'),
PARTITION p1 VALUES LESS THAN ('2015-02-01'),
PARTITION p2 VALUES LESS THAN ('2015-03-01'),
PARTITION p3 VALUES LESS THAN ('2015-04-01'),
PARTITION p4 VALUES LESS THAN ('2015-05-01'),
PARTITION p5 VALUES LESS THAN (MAXVALUE)
);
What are the pro/cons for the new range columns way of partitioning. Is it faster?

What is the mistake in this MySQL partition query?

Please could you tell me the problem with this query:
ALTER TABLE
`phar_bills`
PARTITION BY RANGE COLUMNS (YEAR(bill_date))
(
PARTITION p0 VALUES LESS THAN (2014),
PARTITION p1 VALUES LESS THAN (2015),
PARTITION p2 VALUES LESS THAN (2016),
PARTITION p3 VALUES LESS THAN (2017),
PARTITION p4 VALUES LESS THAN (2018),
PARTITION p5 VALUES LESS THAN (2019),
PARTITION p6 VALUES LESS THAN (2020),
PARTITION p7 VALUES LESS THAN (2021),
PARTITION p8 VALUES LESS THAN (2022),
PARTITION p9 VALUES LESS THAN (2023),
PARTITION p10 VALUES LESS THAN (2024),
PARTITION p11 VALUES LESS THAN (2025),
PARTITION p12 VALUES LESS THAN (2026),
PARTITION p13 VALUES LESS THAN (2027),
PARTITION p14 VALUES LESS THAN (2028),
PARTITION p15 VALUES LESS THAN (2029),
PARTITION p16 VALUES LESS THAN (2030)
)
SUBPARTITION BY LIST COLUMNS(pharmacy_code)
(
PARTITION phar1 VALUES IN('1'),
PARTITION phar2 VALUES IN('2'),
PARTITION phar3 VALUES IN ('3')
)
What is the purpose of the word COLUMNS between RANGE and the partitioning expression?
BY RANGE COLUMNS (YEAR(bill_date))
^^^^^^^
What the plastic is that doing there? I don't believe that's valid syntax, but maybe you're running a newer version of MySQL.
YEAR(bill_date) is an expression, not the name of a column.
According to the MySQL 5.5 Reference Manual:
"RANGE COLUMNS does not accept expressions, only names of columns."
Reference: http://dev.mysql.com/doc/refman/5.5/en/partitioning-columns-range.html
But if that's not valid syntax, we'd fully expect MySQL to throw an error, most likely, a "#1064 You have an error in your syntax".
Aside from that, there are all sorts of other possible issues... but we'd expect most of those to also throw an actual MySQL error message. "partitioning not enabled", "storage engine doesn't support partitioning", "foreign keys not supported on partitioned tables", or some such.

why explain partition shows first partition in every select query?

I have a table named edr on mysql 5.1.6* version. I have partitioned the table using alter -
ALTER TABLE edr PARTITION BY RANGE (TO_DAYS(eventDate))
(
PARTITION apr25 VALUES LESS THAN (TO_DAYS('2014-04-26')),
PARTITION apr26_30 VALUES LESS THAN (TO_DAYS('2014-05-01')),
PARTITION may01_05 VALUES LESS THAN (TO_DAYS('2014-05-06')),
PARTITION may06_10 VALUES LESS THAN (TO_DAYS('2014-05-11')),
PARTITION may11_15 VALUES LESS THAN (TO_DAYS('2014-05-16')),
PARTITION may16_20 VALUES LESS THAN (TO_DAYS('2014-05-21')),
PARTITION may21_25 VALUES LESS THAN (TO_DAYS('2014-05-26')),
PARTITION may26_31 VALUES LESS THAN (TO_DAYS('2014-06-01')),
PARTITION june01_05 VALUES LESS THAN (TO_DAYS('2014-06-06')),
PARTITION june06_10 VALUES LESS THAN (TO_DAYS('2014-06-11')),
PARTITION june11_15 VALUES LESS THAN (TO_DAYS('2014-06-16')));
now when I am running any query for example:
explain partitions select count(*) from edr where eventdate > '2014-05-21';
it gives me output for partitions as - apr25,may21_25, may26_31, jun01_05,jun_06_10,jun11_15.
Here in partition apr25 there is no record for such where condition.
please let me know is any thing wrong in above query or its a partition problem.
It is MySQL bug: explained here.
Try to create a first partition that contains values less than (0)
PARTITION unused VALUES LESS THAN (0);

List partition for remaining items

when partitioning tables in MySQL using a list, how can I generate a partition for remaining items?
E.G:
CREATE TABLE tbl
(
ID integer
)
PARTITION BY LIST (ID)
(
PARTITION P1 values in (1),
PARTITION P2 values in (2),
PARTITION P3 values in (3),
PARTITION Pother values in (<all remaining values of ID>)
);
In Oracle, I use values in (default), but that does work in MySQL.
Unlike range partitioning, there is no "catch-all" in list partitioning. To quote the documentation:
Unlike the case with RANGE partitioning, there is no “catch-all” such
as MAXVALUE; all expected values for the partitioning expression
should be covered in PARTITION ... VALUES IN (...) clauses. An INSERT
statement containing an unmatched partitioning column value fails with
an error...
Unfortunately, I believe, you're not able to combine a list and a range partition either. I'm not entirely certain why you would want to use a list partition in this particular instance; wouldn't a range partition work just a well?
CREATE TABLE tbl
(
ID integer
)
PARTITION BY RANGE (ID)
(
PARTITION P1 values less than (2),
PARTITION P2 values less than (3),
PARTITION P3 values less than (4),
PARTITION Pother values less than maxvalue
);
I'm assuming that this is just an example. Partitioning each key in a primary key is a little pointless.