MYSQL 5.5 partition table by first character 0-9a-zA-Z - mysql

I want to create a range partition on the first character in the character field. The field has hashtag values and is case sensitive 0-9a-zA-Z
I referred to the solution listed here.
This is what I execute:
CREATE TABLE tweetdbq4(hashtag CHAR(50), timestamp CHAR(14), tweetid BIGINT(18) UNSIGNED, userid INT(10) UNSIGNED) ENGINE=MYISAM
PARTITION BY RANGE COLUMNS(hashtag) (
PARTITION p0 VALUES LESS THAN ('a'),
PARTITION p1 VALUES LESS THAN ('b'),
PARTITION p2 VALUES LESS THAN ('c'),
PARTITION p3 VALUES LESS THAN ('d'),
PARTITION p4 VALUES LESS THAN ('e'),
PARTITION p5 VALUES LESS THAN ('f'),
PARTITION p6 VALUES LESS THAN ('g'),
PARTITION p7 VALUES LESS THAN ('h'),
PARTITION p8 VALUES LESS THAN ('i'),
PARTITION p9 VALUES LESS THAN ('j'),
PARTITION p10 VALUES LESS THAN ('k'),
PARTITION p11 VALUES LESS THAN ('l'),
PARTITION p12 VALUES LESS THAN ('m'),
PARTITION p13 VALUES LESS THAN ('n'),
PARTITION p14 VALUES LESS THAN ('o'),
PARTITION p15 VALUES LESS THAN ('p'),
PARTITION p16 VALUES LESS THAN ('q'),
PARTITION p17 VALUES LESS THAN ('r'),
PARTITION p18 VALUES LESS THAN ('s'),
PARTITION p19 VALUES LESS THAN ('t'),
PARTITION p20 VALUES LESS THAN ('u'),
PARTITION p21 VALUES LESS THAN ('v'),
PARTITION p22 VALUES LESS THAN ('w'),
PARTITION p23 VALUES LESS THAN ('x'),
PARTITION p24 VALUES LESS THAN ('y'),
PARTITION p25 VALUES LESS THAN ('z'),
PARTITION p26 VALUES LESS THAN ('A'),
PARTITION p27 VALUES LESS THAN ('B'),
PARTITION p28 VALUES LESS THAN ('C'),
PARTITION p29 VALUES LESS THAN ('D'),
PARTITION p30 VALUES LESS THAN ('E'),
PARTITION p31 VALUES LESS THAN ('F'),
PARTITION p32 VALUES LESS THAN ('G'),
PARTITION p33 VALUES LESS THAN ('H'),
PARTITION p34 VALUES LESS THAN ('I'),
PARTITION p35 VALUES LESS THAN ('J'),
PARTITION p36 VALUES LESS THAN ('K'),
PARTITION p37 VALUES LESS THAN ('L'),
PARTITION p38 VALUES LESS THAN ('M'),
PARTITION p39 VALUES LESS THAN ('N'),
PARTITION p40 VALUES LESS THAN ('O'),
PARTITION p41 VALUES LESS THAN ('P'),
PARTITION p42 VALUES LESS THAN ('Q'),
PARTITION p43 VALUES LESS THAN ('R'),
PARTITION p44 VALUES LESS THAN ('S'),
PARTITION p45 VALUES LESS THAN ('T'),
PARTITION p46 VALUES LESS THAN ('U'),
PARTITION p47 VALUES LESS THAN ('V'),
PARTITION p48 VALUES LESS THAN ('W'),
PARTITION p49 VALUES LESS THAN ('X'),
PARTITION p50 VALUES LESS THAN ('Y'),
PARTITION p51 VALUES LESS THAN ('Z'),
PARTITION p52 VALUES LESS THAN MAXVALUE
);
I get this error
ERROR 1493 (HY000): VALUES LESS THAN value must be strictly increasing for each partition
By doing PARTITION p0 VALUES LESS THAN ('a') will it store partition on values starting from 0-9?
Can you tell me what am I doing wrong? Thanks!

It's because you're using range for partitioning, you have upper and lower case letters. You need to remove one, cause can not use same characters for range.

Plan A: Use a COLLATION for hashtag that ends in _bin, not _ci. "ci" stands for case insensitive. That is 'a' and 'A' are treated equal.
Plan B: Use only 26+1 partitions, not 52+1.
Why are you PARTITIONing? For performance? You probably won't get any performance boost. Let's see a query that you think will be sped up; I will explain why PARTITIONs will or (more likely) won't help.
Unrelated: Why is timestamp a CHAR(14) instead of a TIMESTAMP? CHAR(14) takes 14 or 42 bytes; timestamp takes 4 or 5. Smaller disk footprint leads to better performance.
Unrelated: Are hashtags exactly 50 characters? If not, use VARCHAR, not CHAR. If you argue that "FIXED" is better, I will explain that that is an old wives tale.
Unrelated: Do SHOW CREATE TABLE to see what CHARACTER SET you have. Then think about whether hashtags should be utf8 or not.

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?

Can I partition by 3 variables

I would like to add a third partition to the table below.
As an example, how would I add an subpartition "item_of_sale" for each week_of_sale partition? While I can index this third variable, partitioning by this variable should have much better performance.
alter table MyTable
PARTITION BY RANGE( YEAR_of_Sales )
SUBPARTITION BY HASH(Week_Of_Sales)
SUBPARTITIONS 52 (
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 p2018 VALUES LESS THAN (2019)
PARTITION pmax VALUES LESS THAN MAXVALUE
);

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.

Changing MySQL range partition clause

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)
);