I try to alter an existing table by adding partitioning, but get SQL errors although it looks like the docu says.
Hopefully somebody can point out my mistake.
The table orders has a field called date_order_start, which is DATE, so it has no time information. This field has an index on it. This index is not unique and not part of another unique index.
I want to partition my table by using this statement:
ALTER TABLE orders
PARTITION BY RANGE (date_order_start) (
startpoint VALUES LESS THAN (0),
from20140701 VALUES LESS THAN ('2014-07-01'),
from20140801 VALUES LESS THAN ('2014-08-01'),
from20140901 VALUES LESS THAN ('2014-09-01'),
future VALUES LESS THAN MAXVALUE
);
Error....
Before I tried this:
ALTER TABLE orders
PARTITION BY RANGE (TO_DAYS(date_order_start)) (
startpoint VALUES LESS THAN (0),
from20140701 VALUES LESS THAN (TO_DAYS('2014-07-01')),
from20140801 VALUES LESS THAN (TO_DAYS('2014-08-01')),
from20140901 VALUES LESS THAN (TO_DAYS('2014-09-01')),
future VALUES LESS THAN MAXVALUE
);
But also got an error:
**Error Code: 1064**. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from20140701 VALUES LESS THAN ('2014-07-01'), from20140801 VALUES LESS T' at line 4
Well.... that does not help.
Can anybody spot the error?
Also variation without the startpoint statement didn't work. I thought maybe the (0) was the problem.
I used these pages for information:
http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html
http://dev.mysql.com/doc/refman/5.5/en/alter-table-partition-operations.html
I'm wondering if you're just missing the partition keyword:
ALTER TABLE orders
PARTITION BY RANGE (date_order_start) (
PARTITION startpoint VALUES LESS THAN (0),
PARTITION from20140701 VALUES LESS THAN ('2014-07-01'),
PARTITION from20140801 VALUES LESS THAN ('2014-08-01'),
PARTITION from20140901 VALUES LESS THAN ('2014-09-01'),
PARTITION future VALUES LESS THAN MAXVALUE
);
Also, is the VALUES LESS THAN (0) part really necessary?
Related
I'm trying to partition my very large MySQL table called companyScores (60million rows and 50 columns).
Basically, the table features companies (with the column varchar "company_idx" with unique IDs going from 0 to 10,000 companies) and their respective timestamp (with the column "timestamp") and scores "Scores" (with the column "Scores").
I'd like to include around 500 companies into each partition.
Please let me know if the following would do the job?
ALTER TABLE `companyScores`
PARTITION BY RANGE( company_idx ) (
PARTITION p0 VALUES LESS THAN (500),
PARTITION p1 VALUES LESS THAN (1000),
PARTITION p2 VALUES LESS THAN (1500),
PARTITION p3 VALUES LESS THAN (2000),
and so on...
);
Would the above work?
Also, can we easily insert new values into this database once it has been partitioned?
Would the above work?
No. For several reasons.
If company_idx is a varchar, you need to use RANGE COLUMNS. The RANGE partitioning only works on integers. If you try to use RANGE partitioning on a varchar, you get this error:
ERROR 1659 (HY000): Field 'company_idx' is of a not allowed type for this type of partitioning
Assuming you correct that, you have another problem:
Your partition clauses use integer values, not quoted string values. Those are different types, and the partitioning engine won't use them for defining partitions. If you try, you'll this this error:
ERROR 1654 (HY000): Partition column values of incorrect type
Assuming you correct that by quoting the numbers, you have another problem:
You list the partition for 500 before the string 1000, but the string '500' should come after the string '1000' lexically. RANGE or RANGE COLUMNS partitions must be declared in increasing order. If you try to do it in the order you have, you'll get this error:
ERROR 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition
Assuming you correct the order, it works, but it might not do what you want:
CREATE TABLE `companyScores` (
`company_idx` varchar(10) NOT NULL,
PRIMARY KEY (`company_idx`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
/*!50500 PARTITION BY RANGE COLUMNS(company_idx)
(PARTITION p1 VALUES LESS THAN ('1000') ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN ('1500') ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN ('2000') ENGINE = InnoDB,
PARTITION p0 VALUES LESS THAN ('500') ENGINE = InnoDB) */
Now another question you asked:
Also, can we easily insert new values into this database once it has been partitioned?
If you insert a new value that isn't covered by the partitions you defined, you'll get this error:
mysql> insert into companyScores set company_idx = '700';
ERROR 1526 (HY000): Table has no partition for value from column_list
Why is that? You have a partition for company_idx less than 1000 right?
No. You have a partition for company_idx less than the string '1000'. You tried to insert the string '700', which is lexically greater than '500', as well as all the other partitions. Therefore it's beyond any of the partitions defined.
You could solve all of the above problems if you change your customer_idx to an integer column.
MySQL throwing error while creating partitions on table.
Error Code : 1486
Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed.
I have tried following query :
alter table test.tbl1
partition by range(unix_timestamp(sys_time))
(
PARTITION p20151001 VALUES LESS THAN (unix_timestamp('2015-10-01')),
PARTITION p20151101 VALUES LESS THAN (unix_timestamp('2015-11-01')),
PARTITION p20151201 VALUES LESS THAN (unix_timestamp('2015-12-01')),
PARTITION p20160101 VALUES LESS THAN (unix_timestamp('2016-01-01')),
PARTITION p20160201 VALUES LESS THAN (unix_timestamp('2016-02-01')),
PARTITION p20160301 VALUES LESS THAN (unix_timestamp('2016-03-01'))
);
How can I round this problem.
Thanks in Advance
Reading here it may be possible that you are using MYSQL 5.1:
https://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html
Another pain point in MySQL 5.1 is the handling of date columns. You
can't use them directly, but you need to convert such columns using
either YEAR or TO_DAYS
If your column sys_time is a DATETIME, you dont need to specify the timestamp in order to partition it, you just need to do TO_DAYS, since you're not doing it by year:
alter table test.tbl1
partition by range (TO_DAYS(sys_time))
(
PARTITION p20151001 VALUES LESS THAN (TO_DAYS('2015-10-01')),
PARTITION p20151101 VALUES LESS THAN (TO_DAYS('2015-11-01')),
PARTITION p20151201 VALUES LESS THAN (TO_DAYS('2015-12-01')),
PARTITION p20160101 VALUES LESS THAN (TO_DAYS('2016-01-01')),
PARTITION p20160201 VALUES LESS THAN (TO_DAYS('2016-02-01')),
PARTITION p20160301 VALUES LESS THAN (TO_DAYS('2016-03-01'))
);
if sys_time is a TIMESTAMP then you dont need to convert your timestamp to a timestamp, I have taken that out of the range parameter:
alter table test.tbl1
partition by range(sys_time)
(
PARTITION p20151001 VALUES LESS THAN (unix_timestamp('2015-10-01')),
PARTITION p20151101 VALUES LESS THAN (unix_timestamp('2015-11-01')),
PARTITION p20151201 VALUES LESS THAN (unix_timestamp('2015-12-01')),
PARTITION p20160101 VALUES LESS THAN (unix_timestamp('2016-01-01')),
PARTITION p20160201 VALUES LESS THAN (unix_timestamp('2016-02-01')),
PARTITION p20160301 VALUES LESS THAN (unix_timestamp('2016-03-01'))
);
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);
Hopefully quite simple, and probably obvious, but what is wrong with my syntax. I've been wrestling with this all morning.
I created a set of partitions thus:
ALTER TABLE `schemaName`.`tableName`
PARTITION BY RANGE (TO_DAYS(`Created`)) (
PARTITION `early` VALUES LESS THAN (TO_DAYS('2013-01-01 00:00:00')),
PARTITION `201301` VALUES LESS THAN (TO_DAYS('2013-02-01 00:00:00')),
PARTITION `201302` VALUES LESS THAN (TO_DAYS('2013-03-01 00:00:00')),
PARTITION `201303` VALUES LESS THAN (TO_DAYS('2013-04-01 00:00:00')),
PARTITION `201304` VALUES LESS THAN MAXVALUE
);
So far so good, the last partition now holds data for anything after 1st April (e.g. April and May).
Now I want to reorganize that partition (201304) so that it holds data for just April, and the data for May is moved into a new 'last' partition. My syntax is:
ALTER TABLE `schemaName`.`tableName` REORGANIZE PARTITION `201304` INTO
(
`201304` VALUES LESS THAN (TO_DAYS('2013-05-01 00:00:00')),
`201305` VALUES LESS THAN MAXVALUE
);
But I get an error which suggests the issue is at the first definition ( 201304` VALUES LESS . . . )
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`201304` VALUES LESS THAN (TO_DAYS('2013-05-01 00:00:00')),
#-->ALL DATA BEFORE ' at line 3
If anyone can spot the error I would be very grateful.
Having scoured the internet for an example, I eventually found an example in an old book I had:
ALTER TABLE `schemaName`.`tableName` REORGANIZE PARTITION `201304` INTO
(
PARTITION `201304` VALUES LESS THAN (TO_DAYS('2013-05-01 00:00:00')),
PARTITION `201305` VALUES LESS THAN MAXVALUE
);
Sorry, I don't know English, but I need help :(
I'm using partitioning by LIST COLUMNS by ALTER TABLE statement
My table :
table member_list:
id int,
name varchar(255),
company varchar(255),
cell_phone varchar(20)
It's haven't key
I have more than 900.000 records in the current. After inserting, I tried partitioning table by LIST COLUMNS :
alter table member_list
partition by list columns(company)(
partition p1 values in ('Lavasoft','Cakewalk','Lycos'),
partition p2 values in ('Adobe','Vivoo','Apple Systems','Sibelius'),
partition p3 values in ('Finale','Borland','Macromedia','FPT'),
partition p4 values in ('Chami','Yahoo','Google','Altavista')
)
After runned :
#1526 - Table has no partition for value from column_list
MySQL returned me this error, I can not find support from Oracle page. I hope you will help me. Thanks
#1526 - Table has no partition for value from column_list
The error message is telling you that there is a value in your data in one of the columns you have chosen for partitioning that is not accounted for in your defined partitions.
In this case, there is something in the "company" field that cannot be placed into any of the partitions. For instance, on some record, company="Blackberry." MySQL cannot put this row into any of your partitions.
LIST partitioning allow only Integer values. If you want to use columns with varchar partitioning use HASH or KEY PARTITIONS. Besides partition can only be used on columns that have primary or unique attribute.