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.1, it is possible to match against
only a list of integers (and possibly
NULL—see
Section 17.2.6, “How MySQL Partitioning Handles NULL”) when
partitioning by LIST.
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 12.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 17.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.
All rows relating to employees working at stores in that region
can be deleted with an ALTER TABLE employees DROP
PARTITION pWest statement, which can be executed much
more efficiently than the equivalent
DELETE statement (DELETE
FROM employees WHERE store_id IN (4,12,13,14,18)).
However, the ALTER
TABLE ... DROP PARTITION statement also removes the
partition itself from the definition for the table, and you must
execute an ALTER
TABLE ... ADD PARTITION statement to restore the
table's original partitioning scheme. (This problem is
resolved in MySQL 5.5, which adds the
ALTER TABLE ...
TRUNCATE PARTITION statement for removing all rows
from a given partition without affecting the table definition.)
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 17.2.5, “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 3 mysql>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: 0 mysql>SELECT * FROM h2;+------+------+ | c1 | c2 | +------+------+ | 7 | 5 | | 1 | 9 | | 2 | 5 | +------+------+ 3 rows in set (0.00 sec)

User Comments
Add your own comment.