Spec-Zone .ru
спецификации, руководства, описания, API
|
List partitioning in MySQL is similar to range partitioning in many ways. As in partitioning by RANGE
, each partition must be explicitly defined. The chief difference between the
two types of partitioning is that, in list partitioning, each partition is defined and selected based on the
membership of a column value in one of a set of value lists, rather than in one of a set of contiguous ranges of
values. This is done by using PARTITION BY LIST(
where expr
)expr
is a column value or an expression based on a column value
and returning an integer value, and then defining each partition by means of a VALUES IN (
, where value_list
)value_list
is a comma-separated list of integers.
In MySQL 5.6, it is possible to match against only a list of integers (and possibly NULL
—see Section 18.2.7,
"How MySQL Partitioning Handles NULL
") when partitioning by LIST
.
However, other column types may be used in value lists when employing LIST
COLUMN
partitioning, which is described later in this section.
Unlike the case with partitions defined by range, list partitions do not need to be declared in any particular
order. For more detailed syntactical information, see Section 13.1.17, "CREATE TABLE
Syntax".
For the examples that follow, we assume that the basic definition of the table to be partitioned is provided by
the CREATE TABLE
statement shown here:
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, store_id INT);
(This is the same table used as a basis for the examples in Section
18.2.1, "RANGE
Partitioning".)
Suppose that there are 20 video stores distributed among 4 franchises as shown in the following table.
Region | Store ID Numbers |
---|---|
North | 3, 5, 6, 9, 17 |
East | 1, 2, 10, 11, 19, 20 |
West | 4, 12, 13, 14, 18 |
Central | 7, 8, 15, 16 |
To partition this table in such a way that rows for stores belonging to the same region are stored in the same
partition, you could use the CREATE
TABLE
statement shown here:
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, store_id INT)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));
This makes it easy to add or drop employee records relating to specific regions to or from the table. For
instance, suppose that all stores in the West region are sold to another company. In MySQL 5.6, all rows
relating to employees working at stores in that region can be deleted with the query ALTER
TABLE employees TRUNCATE PARTITION pWest
, which can be executed much more efficiently than the
equivalent DELETE
statement DELETE FROM employees WHERE store_id IN (4,12,13,14,18);
. (Using ALTER TABLE employees DROP PARTITION pWest
would also delete all of these rows,
but would also remove the partition pWest
from the definition of the table; you
would need to use an ALTER TABLE ... ADD PARTITION
statement to restore the table's
original partitioning scheme.)
As with RANGE
partitioning, it is possible to combine LIST
partitioning with partitioning by hash or key to produce a composite
partitioning (subpartitioning). See Section 18.2.6, "Subpartitioning".
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, as shown in this example:
mysql>CREATE TABLE h2 (
->c1 INT,
->c2 INT
->)
->PARTITION BY LIST(c1) (
->PARTITION p0 VALUES IN (1, 4, 7),
->PARTITION p1 VALUES IN (2, 5, 8)
->);
Query OK, 0 rows affected (0.11 sec)mysql>INSERT INTO h2 VALUES (3, 5);
ERROR 1525 (HY000): Table has no partition for value 3
When inserting multiple rows using a single INSERT
statement, any rows coming before the row containing the unmatched value are inserted, but any coming after it
are not:
mysql>SELECT * FROM h2;
Empty set (0.00 sec)mysql>INSERT INTO h2 VALUES (4, 7), (3, 5), (6, 0);
ERROR 1525 (HY000): Table has no partition for value 3mysql>SELECT * FROM h2;
+------+------+| c1 | c2 |+------+------+| 4 | 7 |+------+------+1 row in set (0.00 sec)
You can cause this type of error to be ignored by using the IGNORE
keyword. If you
do so, rows containing unmatched partitioning column values are not inserted, but any rows with matching values
are inserted, and no errors are reported:
mysql>TRUNCATE h2;
Query OK, 1 row affected (0.00 sec)mysql>SELECT * FROM h2;
Empty set (0.00 sec)mysql>INSERT IGNORE INTO h2 VALUES (2, 5), (6, 10), (7, 5), (3, 1), (1, 9);
Query OK, 3 rows affected (0.00 sec)Records: 5 Duplicates: 2 Warnings: 0mysql>SELECT * FROM h2;
+------+------+| c1 | c2 |+------+------+| 7 | 5 || 1 | 9 || 2 | 5 |+------+------+3 rows in set (0.00 sec)
MySQL 5.6 provides support for LIST COLUMNS
partitioning. This is a variant of
LIST
partitioning that enables you to use columns of types other than integer types
for partitioning columns, as well as to use multiple columns as partitioning keys. For more information, see Section 18.2.3.2, "LIST COLUMNS
partitioning".