A Brief analysis of Mysql Data Table Partitioning Technology

  • 2020-06-19 11:49:25
  • OfStack

In this section, look at the partitioning techniques in Mysql (RANGE, LIST, HASH)

The partitioning technique of Mysql is similar to the horizontal partitioning table, but it is a horizontal partitioning table at the logical level. For the application, it is still a table. In other words, the partition does not actually split a table.

There are several partition types in Mysql 5.1(after) :

RANGE partition: Assigns multiple rows to a partition based on column values belonging to a given continuous interval

LIST partitioning: Similar to RANGE partitioning, except that LIST partitioning is based on column values matching a value from a discrete set of values

HASH partitioning: Selects partitions based on the return value of a user-defined expression that evaluates to the column values of the rows to be inserted into the table, and this function can contain any expression that is valid in Mysql and produces non-negative integer values

KEY partitions: They have been partitioned as HASH, but the difference is that the KEY partition only supports one or more columns, and the Mysql server provides its own hash function

Precautions for partitioning:

1, do the partition, or do not define the primary key, or add the partition field to the primary key
2, the partition field cannot be NULL, otherwise how to determine the partition scope, so try NOT NULL

First you can check to see if your version of Mysql supports PARTITION


mysql> show plugins;
 
| partition    | ACTIVE   | STORAGE ENGINE     | NULL    | GPL     |

Or:
 
mysql> show variables like "%part%";
 
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+

RANGE partition

Suppose you create a table that holds records of the staff of 20 video stores numbered from 1 to 20. If you want to divide it into four smaller partitions, you can use the RANGE partition to create the following database table:

mysql-> CREATE TABLE employees (
     ->     id INT NOT NULL,
     ->     fname VARCHAR(30),
     ->     lname VARCHAR(30),
     ->     hired DATE NOT NULL DEFAULT '1970-01-01',
     ->     separated DATE NOT NULL DEFAULT '9999-12-31',
     ->     job_code INT NOT NULL,
     ->     store_id INT NOT NULL
     -> ) ENGINE=Myisam DEFAULT CHARSET=utf8
     -> PARTITION BY RANGE (store_id) (
     ->     PARTITION P0 VALUES LESS THAN (6),
     ->     PARTITION P1 VALUES LESS THAN (11),
     ->     PARTITION P2 VALUES LESS THAN (16),
     ->     PARTITION P3 VALUES LESS THAN (21)
     -> );

If you want to store employees who have left at different times separately, you can use the date field separated as one key. The SQL statement created is as follows:

mysql-> CREATE TABLE employees (
     ->     id INT NOT NULL,
     ->     fname VARCHAR(30),
     ->     lname VARCHAR(30),
     ->     hired DATE NOT NULL DEFAULT '1970-01-01',
     ->     separated DATE NOT NULL DEFAULT '9999-12-31',
     ->     job_code INT NOT NULL,
     ->     store_id INT NOT NULL
     -> ) ENGINE=Myisam DEFAULT CHARSET=utf8
     -> PARTITION BY RANGE (YEAR(separated)) (
     ->     PARTITION P0 VALUES LESS THAN (2001),
     ->     PARTITION P1 VALUES LESS THAN (2011),
     ->     PARTITION P2 VALUES LESS THAN (2021),
     ->     PARTITION P3 VALUES LESS THAN MAXVALUE
     -> );


List partition

In the same example, if the 20 video stores are located in four distribution areas,

+------------------+--------------------------------------+
| region              | Video store ID No.                          |
+------------------+--------------------------------------+
| North district              | 3, 5, 6, 9, 17                       |
| east area              | 1, 2, 10, 11, 19, 20                 |
| west area              | 4, 12, 13, 14, 18                    |
| Central business district            | 7, 8, 15, 16                         |
+------------------+--------------------------------------+
 
mysql-> CREATE TABLE employees (
     ->     id INT NOT NULL,
     ->     fname VARCHAR(30),
     ->     lname VARCHAR(30),
     ->     hired DATE NOT NULL DEFAULT '1970-01-01',
     ->     separated DATE NOT NULL DEFAULT '9999-12-31',
     ->     job_code INT NOT NULL,
     ->     store_id INT NOT NULL
     -> ) ENGINE=Myisam DEFAULT CHARSET=utf8
     -> PARTITION BY LIST (store_id) (
     ->     PARTITION pNorth   VALUES IN (3, 5, 6, 9, 17),
     ->     PARTITION pEast    VALUES IN (1, 2, 10, 11, 19, 20),
     ->     PARTITION pWest    VALUES IN (4, 12, 13, 14, 18),
     ->     PARTITION pCentral VALUES IN (7, 8, 15, 16)
     -> );


When you are done, you can go to the Mysql data store file, whose location is defined in the Mysql configuration file


shawn@Shawn:~$ sudo vi /etc/mysql/my.cnf;
 
[mysqld]
datadir         = /var/lib/mysql
 
shawn@Shawn:~$ cd /var/lib/mysql/dbName
shawn@Shawn:/var/lib/mysql/dbName$ ll
 
According to the following :
8768 Jun  7 22:01 employees.frm
  48 Jun  7 22:01 employees.par
   0 Jun  7 22:01 employees#P#pCentral.MYD
1024 Jun  7 22:01 employees#P#pCentral.MYI
   0 Jun  7 22:01 employees#P#pEast.MYD
1024 Jun  7 22:01 employees#P#pEast.MYI
   0 Jun  7 22:01 employees#P#pNorth.MYD
1024 Jun  7 22:01 employees#P#pNorth.MYI
   0 Jun  7 22:01 employees#P#pWest.MYD
1024 Jun  7 22:01 employees#P#pWest.MYI

As you can see here, it splits the storage file according to our definition

employees.frm = Table structure
employees.par = partition, Statement is 1 A partition table
.MYD = The data file
.MYI = Index file
 

HASH partition

HASH partitions are used primarily to ensure that data is evenly distributed among a predetermined number of partitions
If you want to store employees who joined at different times separately, you can use the date field hired as an key

mysql-> CREATE TABLE employees (
     ->     id INT NOT NULL,
     ->     fname VARCHAR(30),
     ->     lname VARCHAR(30),
     ->     hired DATE NOT NULL DEFAULT '1970-01-01',
     ->     separated DATE NOT NULL DEFAULT '9999-12-31',
     ->     job_code INT NOT NULL,
     ->     store_id INT NOT NULL
     -> ) ENGINE=Myisam DEFAULT CHARSET=utf8
     -> PARTITION BY HASH (YEAR(hired)) (
     ->     PARTITIONS 4
     -> );
     
# The thing to notice here is that PARTITIONS . Much more 1 a s

One thing to note here is that the example above USES the Myisam storage engine, which USES separate tablespaces by default, so you can see the different partitions in the disk space above
The InnoDB engine USES Shared table space by default. Even if you partition the InnoDB table, you will find that it is not physically partitioned like Myisam, so you need to modify the Mysql configuration file:

shawn@Shawn:~$ sudo vi /etc/mysql/my.cnf;
 
# add :
innodb_file_per_table=1
 
# restart mysql
shawn@Shawn:~$ sudo /etc/init.d/mysql restart

If you partition InooDB, it will have the following effect:

8768 Jun  7 22:54 employees.frm
   48 Jun  7 22:54 employees.par
98304 Jun  7 22:54 employees#P#pCentral.ibd
98304 Jun  7 22:54 employees#P#pEast.ibd
98304 Jun  7 22:54 employees#P#pNorth.ibd
98304 Jun  7 22:54 employees#P#pWest.ibd

Partition management

Deleted partitions
 
mysql> show variables like "%part%";
 
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| have_partitioning | YES   |
+-------------------+-------+
0
The new partition

#range Add a new partition  
mysql> alter table employees add partition ( partition p4 values less than (26) ); 
  
#list Add a new partition  
mysql> alter table employees add partition( partition pSouth values in (21, 22, 23) ); 
  
#hash To partition  
mysql> alter table employees add partition partitions 5; 


Related articles: