22.6 Restrictions and Limitations on Partitioning

This section discusses current restrictions and limitations on MySQL partitioning support.

Prohibited constructs

The following constructs are not permitted in partitioning expressions:

For a list of SQL functions which are permitted in partitioning expressions, see *note partitioning-limitations-functions::.

Arithmetic and logical operators

Use of the arithmetic operators '+', '-', and '' is permitted in partitioning expressions. However, the result must be an integer value or 'NULL' (except in the case of '[LINEAR] KEY' partitioning, as discussed elsewhere in this chapter; see note partitioning-types::, for more information).

The 'DIV' operator is also supported, and the '/' operator is not permitted. (Bug #30188, Bug #33182)

The bit operators '|', '&', '^', '<<', '>>', and '~' are not permitted in partitioning expressions.

HANDLER statements

Previously, the *note 'HANDLER': handler. statement was not supported with partitioned tables. This limitation is removed beginning with MySQL 5.7.1.

Server SQL mode

Tables employing user-defined partitioning do not preserve the SQL mode in effect at the time that they were created. As discussed in *note sql-mode::, the results of many MySQL functions and operators may change according to the server SQL mode. Therefore, a change in the SQL mode at any time after the creation of partitioned tables may lead to major changes in the behavior of such tables, and could easily lead to corruption or loss of data. For these reasons, it is strongly recommended that you never change the server SQL mode after creating partitioned tables.

Examples

The following examples illustrate some changes in behavior of partitioned tables due to a change in the server SQL mode:

  1. Error handling

    Suppose that you create a partitioned table whose partitioning expression is one such as 'COLUMN DIV 0' or 'COLUMN MOD 0', as shown here:

      mysql> CREATE TABLE tn (c1 INT)
          ->     PARTITION BY LIST(1 DIV c1) (
          ->       PARTITION p0 VALUES IN (NULL),
          ->       PARTITION p1 VALUES IN (1)
          -> );
      Query OK, 0 rows affected (0.05 sec)

    The default behavior for MySQL is to return 'NULL' for the result of a division by zero, without producing any errors:

      mysql> SELECT @@sql_mode;
      +------------+
      | @@sql_mode |
      +------------+
      |            |
      +------------+
      1 row in set (0.00 sec)
    
      mysql> INSERT INTO tn VALUES (NULL), (0), (1);
      Query OK, 3 rows affected (0.00 sec)
      Records: 3  Duplicates: 0  Warnings: 0

    However, changing the server SQL mode to treat division by zero as an error and to enforce strict error handling causes the same *note 'INSERT': insert. statement to fail, as shown here:

      mysql> SET sql_mode='STRICT_ALL_TABLES,ERROR_FOR_DIVISION_BY_ZERO';
      Query OK, 0 rows affected (0.00 sec)
    
      mysql> INSERT INTO tn VALUES (NULL), (0), (1);
      ERROR 1365 (22012): Division by 0
  2. Table accessibility

    Sometimes a change in the server SQL mode can make partitioned tables unusable. The following *note 'CREATE TABLE': create-table. statement can be executed successfully only if the 'NO_UNSIGNED_SUBTRACTION' mode is in effect:

      mysql> SELECT @@sql_mode;
      +------------+
      | @@sql_mode |
      +------------+
      |            |
      +------------+
      1 row in set (0.00 sec)
    
      mysql> CREATE TABLE tu (c1 BIGINT UNSIGNED)
          ->   PARTITION BY RANGE(c1 - 10) (
          ->     PARTITION p0 VALUES LESS THAN (-5),
          ->     PARTITION p1 VALUES LESS THAN (0),
          ->     PARTITION p2 VALUES LESS THAN (5),
          ->     PARTITION p3 VALUES LESS THAN (10),
          ->     PARTITION p4 VALUES LESS THAN (MAXVALUE)
          -> );
      ERROR 1563 (HY000): Partition constant is out of partition function domain
    
      mysql> SET sql_mode='NO_UNSIGNED_SUBTRACTION';
      Query OK, 0 rows affected (0.00 sec)
    
      mysql> SELECT @@sql_mode;
      +-------------------------+
      | @@sql_mode              |
      +-------------------------+
      | NO_UNSIGNED_SUBTRACTION |
      +-------------------------+
      1 row in set (0.00 sec)
    
      mysql> CREATE TABLE tu (c1 BIGINT UNSIGNED)
          ->   PARTITION BY RANGE(c1 - 10) (
          ->     PARTITION p0 VALUES LESS THAN (-5),
          ->     PARTITION p1 VALUES LESS THAN (0),
          ->     PARTITION p2 VALUES LESS THAN (5),
          ->     PARTITION p3 VALUES LESS THAN (10),
          ->     PARTITION p4 VALUES LESS THAN (MAXVALUE)
          -> );
      Query OK, 0 rows affected (0.05 sec)

    If you remove the 'NO_UNSIGNED_SUBTRACTION' server SQL mode after creating 'tu', you may no longer be able to access this table:

      mysql> SET sql_mode='';
      Query OK, 0 rows affected (0.00 sec)
    
      mysql> SELECT * FROM tu;
      ERROR 1563 (HY000): Partition constant is out of partition function domain
      mysql> INSERT INTO tu VALUES (20);
      ERROR 1563 (HY000): Partition constant is out of partition function domain

    See also *note sql-mode::.

Server SQL modes also impact replication of partitioned tables. Disparate SQL modes on source and replica can lead to partitioning expressions being evaluated differently; this can cause the distribution of data among partitions to be different in the source's and replica's copies of a given table, and may even cause inserts into partitioned tables that succeed on the source to fail on the replica. For best results, you should always use the same server SQL mode on the source and on the replica.

Performance considerations

Some effects of partitioning operations on performance are given in the following list:

Maximum number of partitions

The maximum possible number of partitions for a given table not using the *note 'NDB': mysql-cluster. storage engine is 8192. This number includes subpartitions.

The maximum possible number of user-defined partitions for a table using the note 'NDB': mysql-cluster. storage engine is determined according to the version of the NDB Cluster software being used, the number of data nodes, and other factors. See note mysql-cluster-nodes-groups-user-partitioning::, for more information.

If, when creating tables with a large number of partitions (but less than the maximum), you encounter an error message such as 'Got error ... from storage engine: Out of resources when opening file', you may be able to address the issue by increasing the value of the 'open_files_limit' system variable. However, this is dependent on the operating system, and may not be possible or advisable on all platforms; see *note not-enough-file-handles::, for more information. In some cases, using large numbers (hundreds) of partitions may also not be advisable due to other concerns, so using more partitions does not automatically lead to better results.

See also *note partitioning-limitations-file-system-ops::.

Query cache not supported

The query cache is not supported for partitioned tables, and is automatically disabled for queries involving partitioned tables. The query cache cannot be enabled for such queries.

Per-partition key caches

In MySQL 5.7, key caches are supported for partitioned note 'MyISAM': myisam-storage-engine. tables, using the note 'CACHE INDEX': cache-index. and *note 'LOAD INDEX INTO CACHE': load-index. statements. Key caches may be defined for one, several, or all partitions, and indexes for one, several, or all partitions may be preloaded into key caches.

Foreign keys not supported for partitioned InnoDB tables

Partitioned tables using the *note 'InnoDB': innodb-storage-engine. storage engine do not support foreign keys. More specifically, this means that the following two statements are true:

  1. No definition of an 'InnoDB' table employing user-defined partitioning may contain foreign key references; no 'InnoDB' table whose definition contains foreign key references may be partitioned.

  2. No 'InnoDB' table definition may contain a foreign key reference to a user-partitioned table; no 'InnoDB' table with user-defined partitioning may contain columns referenced by foreign keys.

The scope of the restrictions just listed includes all tables that use the 'InnoDB' storage engine. note 'CREATE TABLE': create-table-foreign-keys. and note 'ALTER TABLE': alter-table. statements that would result in tables violating these restrictions are not allowed.

ALTER TABLE ... ORDER BY

An 'ALTER TABLE ... ORDER BY COLUMN' statement run against a partitioned table causes ordering of rows only within each partition.

Effects on REPLACE statements by modification of primary keys

It can be desirable in some cases (see note partitioning-limitations-partitioning-keys-unique-keys::) to modify a table's primary key. Be aware that, if your application uses note 'REPLACE': replace. statements and you do this, the results of these statements can be drastically altered. See *note replace::, for more information and an example.

FULLTEXT indexes

Partitioned tables do not support 'FULLTEXT' indexes or searches, even for partitioned tables employing the note 'InnoDB': innodb-storage-engine. or note 'MyISAM': myisam-storage-engine. storage engine.

Spatial columns

Columns with spatial data types such as 'POINT' or 'GEOMETRY' cannot be used in partitioned tables.

Temporary tables

Temporary tables cannot be partitioned. (Bug #17497)

Log tables

It is not possible to partition the log tables; an *note 'ALTER TABLE ... PARTITION BY ...': alter-table-partition-operations. statement on such a table fails with an error.

Data type of partitioning key

A partitioning key must be either an integer column or an expression that resolves to an integer. Expressions employing note 'ENUM': enum. columns cannot be used. The column or expression value may also be 'NULL'. (See note partitioning-handling-nulls::.)

There are two exceptions to this restriction:

  1. When partitioning by ['LINEAR'] 'KEY', it is possible to use columns of any valid MySQL data type other than note 'TEXT': blob. or note 'BLOB': blob. as partitioning keys, because MySQL's internal key-hashing functions produce the correct data type from these types. For example, the following two *note 'CREATE TABLE': create-table. statements are valid:

      CREATE TABLE tkc (c1 CHAR)
      PARTITION BY KEY(c1)
      PARTITIONS 4;
    
      CREATE TABLE tke
          ( c1 ENUM('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet') )
      PARTITION BY LINEAR KEY(c1)
      PARTITIONS 6;
  2. When partitioning by 'RANGE COLUMNS' or 'LIST COLUMNS', it is possible to use string, note 'DATE': datetime, and note 'DATETIME': datetime. columns. For example, each of the following *note 'CREATE TABLE': create-table. statements is valid:

      CREATE TABLE rc (c1 INT, c2 DATE)
      PARTITION BY RANGE COLUMNS(c2) (
          PARTITION p0 VALUES LESS THAN('1990-01-01'),
          PARTITION p1 VALUES LESS THAN('1995-01-01'),
          PARTITION p2 VALUES LESS THAN('2000-01-01'),
          PARTITION p3 VALUES LESS THAN('2005-01-01'),
          PARTITION p4 VALUES LESS THAN(MAXVALUE)
      );
    
      CREATE TABLE lc (c1 INT, c2 CHAR(1))
      PARTITION BY LIST COLUMNS(c2) (
          PARTITION p0 VALUES IN('a', 'd', 'g', 'j', 'm', 'p', 's', 'v', 'y'),
          PARTITION p1 VALUES IN('b', 'e', 'h', 'k', 'n', 'q', 't', 'w', 'z'),
          PARTITION p2 VALUES IN('c', 'f', 'i', 'l', 'o', 'r', 'u', 'x', NULL)
      );

Neither of the preceding exceptions applies to note 'BLOB': blob. or note 'TEXT': blob. column types.

Subqueries

A partitioning key may not be a subquery, even if that subquery resolves to an integer value or 'NULL'.

Column index prefixes not supported for key partitioning

When creating a table that is partitioned by key, any columns in the partitioning key which use column prefixes are not used in the table's partitioning function. Consider the following note 'CREATE TABLE': create-table. statement, which has three note 'VARCHAR': char. columns, and whose primary key uses all three columns and specifies prefixes for two of them:

 CREATE TABLE t1 (
     a VARCHAR(10000),
     b VARCHAR(25),
     c VARCHAR(10),
     PRIMARY KEY (a(10), b, c(2))
 ) PARTITION BY KEY() PARTITIONS 2;

This statement is accepted, but the resulting table is actually created as if you had issued the following statement, using only the primary key column which does not include a prefix (column 'b') for the partitioning key:

 CREATE TABLE t1 (
     a VARCHAR(10000),
     b VARCHAR(25),
     c VARCHAR(10),
     PRIMARY KEY (a(10), b, c(2))
 ) PARTITION BY KEY(b) PARTITIONS 2;

No warning is issued or any other indication provided that this has occurred, except in the event that all columns specified for the partitioning key use prefixes, in which case the statement fails with the error message shown here:

 mysql> CREATE TABLE t2 (
     ->     a VARCHAR(10000),
     ->     b VARCHAR(25),
     ->     c VARCHAR(10),
     ->     PRIMARY KEY (a(10), b(5), c(2))
     -> ) PARTITION BY KEY() PARTITIONS 2;
 ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the
 table's partitioning function

This also occurs when altering or upgrading such tables, and includes cases in which the columns used in the partitioning function are defined implicitly as those in the table's primary key by employing an empty 'PARTITION BY KEY()' clause.

This is a known issue which is addressed in MySQL 8.0 by deprecating the permissive behavior; in MYSQL 8.0, if any columns using prefixes are included in a table's partitioning function, the server logs an appropriate warning for each such column, or raises a descriptive error if necessary. (Allowing the use of columns with prefixes in partitioning keys is subject to removal altogether in a future version of MySQL.)

For general information about partitioning tables by key, see *note partitioning-key::.

Issues with subpartitions

Subpartitions must use 'HASH' or 'KEY' partitioning. Only 'RANGE' and 'LIST' partitions may be subpartitioned; 'HASH' and 'KEY' partitions cannot be subpartitioned.

'SUBPARTITION BY KEY' requires that the subpartitioning column or columns be specified explicitly, unlike the case with 'PARTITION BY KEY', where it can be omitted (in which case the table's primary key column is used by default). Consider the table created by this statement:

 CREATE TABLE ts (
     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(30)
 );

You can create a table having the same columns, partitioned by 'KEY', using a statement such as this one:

 CREATE TABLE ts (
     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(30)
 )
 PARTITION BY KEY()
 PARTITIONS 4;

The previous statement is treated as though it had been written like this, with the table's primary key column used as the partitioning column:

 CREATE TABLE ts (
     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     name VARCHAR(30)
 )
 PARTITION BY KEY(id)
 PARTITIONS 4;

However, the following statement that attempts to create a subpartitioned table using the default column as the subpartitioning column fails, and the column must be specified for the statement to succeed, as shown here:

 mysql> CREATE TABLE ts (
     ->     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     ->     name VARCHAR(30)
     -> )
     -> PARTITION BY RANGE(id)
     -> SUBPARTITION BY KEY()
     -> SUBPARTITIONS 4
     -> (
     ->     PARTITION p0 VALUES LESS THAN (100),
     ->     PARTITION p1 VALUES LESS THAN (MAXVALUE)
     -> );
 ERROR 1064 (42000): 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 ')

 mysql> CREATE TABLE ts (
     ->     id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
     ->     name VARCHAR(30)
     -> )
     -> PARTITION BY RANGE(id)
     -> SUBPARTITION BY KEY(id)
     -> SUBPARTITIONS 4
     -> (
     ->     PARTITION p0 VALUES LESS THAN (100),
     ->     PARTITION p1 VALUES LESS THAN (MAXVALUE)
     -> );
 Query OK, 0 rows affected (0.07 sec)

This is a known issue (see Bug #51470).

DATA DIRECTORY and INDEX DIRECTORY options

'DATA DIRECTORY' and 'INDEX DIRECTORY' are subject to the following restrictions when used with partitioned tables:

Repairing and rebuilding partitioned tables

The statements note 'CHECK TABLE': check-table, note 'OPTIMIZE TABLE': optimize-table, note 'ANALYZE TABLE': analyze-table, and note 'REPAIR TABLE': repair-table. are supported for partitioned tables.

In addition, you can use 'ALTER TABLE ... REBUILD PARTITION' to rebuild one or more partitions of a partitioned table; 'ALTER TABLE ... REORGANIZE PARTITION' also causes partitions to be rebuilt. See *note alter-table::, for more information about these two statements.

Starting in MySQL 5.7.2, 'ANALYZE', 'CHECK', 'OPTIMIZE', 'REPAIR', and 'TRUNCATE' operations are supported with subpartitions. 'REBUILD' was also accepted syntax prior to MySQL 5.7.5, although this had no effect. (Bug #19075411, Bug #73130) See also *note alter-table-partition-operations::.

note 'mysqlcheck': mysqlcheck, note 'myisamchk': myisamchk, and *note 'myisampack': myisampack. are not supported with partitioned tables.

FOR EXPORT option (FLUSH TABLES)

The 'FLUSH TABLES' statement's 'FOR EXPORT' option is not supported for partitioned 'InnoDB' tables in MySQL 5.7.4 and earlier. (Bug #16943907)

File name delimiters for partitions and subpartitions

Table partition and subpartition file names include generated delimiters such as '#P#' and '#SP#'. The lettercase of such delimiters can vary and should not be depended upon.

 File: manual.info.tmp, Node: partitioning-limitations-partitioning-keys-unique-keys, Next: partitioning-limitations-storage-engines, Prev: partitioning-limitations, Up: partitioning-limitations

22.6.1 Partitioning Keys, Primary Keys, and Unique Keys

This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.

In other words, every unique key on the table must use every column in the table's partitioning expression. (This also includes the table's primary key, since it is by definition a unique key. This particular case is discussed later in this section.) For example, each of the following table creation statements is invalid:

 CREATE TABLE t1 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1, col2)
 )
 PARTITION BY HASH(col3)
 PARTITIONS 4;

 CREATE TABLE t2 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1),
     UNIQUE KEY (col3)
 )
 PARTITION BY HASH(col1 + col3)
 PARTITIONS 4;

In each case, the proposed table would have at least one unique key that does not include all columns used in the partitioning expression.

Each of the following statements is valid, and represents one way in which the corresponding invalid table creation statement could be made to work:

 CREATE TABLE t1 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1, col2, col3)
 )
 PARTITION BY HASH(col3)
 PARTITIONS 4;

 CREATE TABLE t2 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1, col3)
 )
 PARTITION BY HASH(col1 + col3)
 PARTITIONS 4;

This example shows the error produced in such cases:

 mysql> CREATE TABLE t3 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1, col2),
     ->     UNIQUE KEY (col3)
     -> )
     -> PARTITION BY HASH(col1 + col3)
     -> PARTITIONS 4;
 ERROR 1491 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

The *note 'CREATE TABLE': create-table. statement fails because both 'col1' and 'col3' are included in the proposed partitioning key, but neither of these columns is part of both of unique keys on the table. This shows one possible fix for the invalid table definition:

 mysql> CREATE TABLE t3 (
     ->     col1 INT NOT NULL,
     ->     col2 DATE NOT NULL,
     ->     col3 INT NOT NULL,
     ->     col4 INT NOT NULL,
     ->     UNIQUE KEY (col1, col2, col3),
     ->     UNIQUE KEY (col3)
     -> )
     -> PARTITION BY HASH(col3)
     -> PARTITIONS 4;
 Query OK, 0 rows affected (0.05 sec)

In this case, the proposed partitioning key 'col3' is part of both unique keys, and the table creation statement succeeds.

The following table cannot be partitioned at all, because there is no way to include in a partitioning key any columns that belong to both unique keys:

 CREATE TABLE t4 (
     col1 INT NOT NULL,
     col2 INT NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     UNIQUE KEY (col1, col3),
     UNIQUE KEY (col2, col4)
 );

Since every primary key is by definition a unique key, this restriction also includes the table's primary key, if it has one. For example, the next two statements are invalid:

 CREATE TABLE t5 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     PRIMARY KEY(col1, col2)
 )
 PARTITION BY HASH(col3)
 PARTITIONS 4;

 CREATE TABLE t6 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     PRIMARY KEY(col1, col3),
     UNIQUE KEY(col2)
 )
 PARTITION BY HASH( YEAR(col2) )
 PARTITIONS 4;

In both cases, the primary key does not include all columns referenced in the partitioning expression. However, both of the next two statements are valid:

 CREATE TABLE t7 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     PRIMARY KEY(col1, col2)
 )
 PARTITION BY HASH(col1 + YEAR(col2))
 PARTITIONS 4;

 CREATE TABLE t8 (
     col1 INT NOT NULL,
     col2 DATE NOT NULL,
     col3 INT NOT NULL,
     col4 INT NOT NULL,
     PRIMARY KEY(col1, col2, col4),
     UNIQUE KEY(col2, col1)
 )
 PARTITION BY HASH(col1 + YEAR(col2))
 PARTITIONS 4;

If a table has no unique keys--this includes having no primary key--then this restriction does not apply, and you may use any column or columns in the partitioning expression as long as the column type is compatible with the partitioning type.

For the same reason, you cannot later add a unique key to a partitioned table unless the key includes all columns used by the table's partitioning expression. Consider the partitioned table created as shown here:

 mysql> CREATE TABLE t_no_pk (c1 INT, c2 INT)
     ->     PARTITION BY RANGE(c1) (
     ->         PARTITION p0 VALUES LESS THAN (10),
     ->         PARTITION p1 VALUES LESS THAN (20),
     ->         PARTITION p2 VALUES LESS THAN (30),
     ->         PARTITION p3 VALUES LESS THAN (40)
     ->     );
 Query OK, 0 rows affected (0.12 sec)

It is possible to add a primary key to 't_no_pk' using either of these *note 'ALTER TABLE': alter-table-partition-operations. statements:

 #  possible PK
 mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1);
 Query OK, 0 rows affected (0.13 sec)
 Records: 0  Duplicates: 0  Warnings: 0

 # drop this PK
 mysql> ALTER TABLE t_no_pk DROP PRIMARY KEY;
 Query OK, 0 rows affected (0.10 sec)
 Records: 0  Duplicates: 0  Warnings: 0

 #  use another possible PK
 mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c1, c2);
 Query OK, 0 rows affected (0.12 sec)
 Records: 0  Duplicates: 0  Warnings: 0

 # drop this PK
 mysql> ALTER TABLE t_no_pk DROP PRIMARY KEY;
 Query OK, 0 rows affected (0.09 sec)
 Records: 0  Duplicates: 0  Warnings: 0

However, the next statement fails, because 'c1' is part of the partitioning key, but is not part of the proposed primary key:

 #  fails with error 1503
 mysql> ALTER TABLE t_no_pk ADD PRIMARY KEY(c2);
 ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

Since 't_no_pk' has only 'c1' in its partitioning expression, attempting to adding a unique key on 'c2' alone fails. However, you can add a unique key that uses both 'c1' and 'c2'.

These rules also apply to existing nonpartitioned tables that you wish to partition using *note 'ALTER TABLE ... PARTITION BY': alter-table-partition-operations. Consider a table 'np_pk' created as shown here:

 mysql> CREATE TABLE np_pk (
     ->     id INT NOT NULL AUTO_INCREMENT,
     ->     name VARCHAR(50),
     ->     added DATE,
     ->     PRIMARY KEY (id)
     -> );
 Query OK, 0 rows affected (0.08 sec)

The following *note 'ALTER TABLE': alter-table-partition-operations. statement fails with an error, because the 'added' column is not part of any unique key in the table:

 mysql> ALTER TABLE np_pk
     ->     PARTITION BY HASH( TO_DAYS(added) )
     ->     PARTITIONS 4;
 ERROR 1503 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function

However, this statement using the 'id' column for the partitioning column is valid, as shown here:

 mysql> ALTER TABLE np_pk
     ->     PARTITION BY HASH(id)
     ->     PARTITIONS 4;
 Query OK, 0 rows affected (0.11 sec)
 Records: 0  Duplicates: 0  Warnings: 0

In the case of 'np_pk', the only column that may be used as part of a partitioning expression is 'id'; if you wish to partition this table using any other column or columns in the partitioning expression, you must first modify the table, either by adding the desired column or columns to the primary key, or by dropping the primary key altogether.

 File: manual.info.tmp, Node: partitioning-limitations-storage-engines, Next: partitioning-limitations-functions, Prev: partitioning-limitations-partitioning-keys-unique-keys, Up: partitioning-limitations

22.6.2 Partitioning Limitations Relating to Storage Engines

The following limitations apply to the use of storage engines with user-defined partitioning of tables.

MERGE storage engine

User-defined partitioning and the 'MERGE' storage engine are not compatible. Tables using the 'MERGE' storage engine cannot be partitioned. Partitioned tables cannot be merged.

FEDERATED storage engine

Partitioning of 'FEDERATED' tables is not supported; it is not possible to create partitioned 'FEDERATED' tables.

CSV storage engine

Partitioned tables using the 'CSV' storage engine are not supported; it is not possible to create partitioned 'CSV' tables.

InnoDB storage engine

*note 'InnoDB': innodb-storage-engine. foreign keys and MySQL partitioning are not compatible. Partitioned 'InnoDB' tables cannot have foreign key references, nor can they have columns referenced by foreign keys. 'InnoDB' tables which have or which are referenced by foreign keys cannot be partitioned.

'InnoDB' does not support the use of multiple disks for subpartitions. (This is currently supported only by 'MyISAM'.)

In addition, note 'ALTER TABLE ... OPTIMIZE PARTITION': alter-table-partition-operations. does not work correctly with partitioned tables that use the 'InnoDB' storage engine. Use 'ALTER TABLE ... REBUILD PARTITION' and 'ALTER TABLE ... ANALYZE PARTITION', instead, for such tables. For more information, see note alter-table-partition-operations::.

User-defined partitioning and the NDB storage engine (NDB Cluster)

Partitioning by 'KEY' (including 'LINEAR KEY') is the only type of partitioning supported for the *note 'NDB': mysql-cluster. storage engine. It is not possible under normal circumstances in NDB Cluster to create an NDB Cluster table using any partitioning type other than ['LINEAR'] 'KEY', and attempting to do so fails with an error.

Exception (not for production): It is possible to override this restriction by setting the 'new' system variable on NDB Cluster SQL nodes to 'ON'. If you choose to do this, you should be aware that tables using partitioning types other than '[LINEAR] KEY' are not supported in production. In such cases, you can create and use tables with partitioning types other than 'KEY' or 'LINEAR KEY', but you do this entirely at your own risk. You should also be aware that this functionality is now deprecated and subject to removal without further notice in a future release of NDB Cluster.

The maximum number of partitions that can be defined for an note 'NDB': mysql-cluster. table depends on the number of data nodes and node groups in the cluster, the version of the NDB Cluster software in use, and other factors. See note mysql-cluster-nodes-groups-user-partitioning::, for more information.

As of MySQL NDB Cluster 7.5.2, the maximum amount of fixed-size data that can be stored per partition in an 'NDB' table is 128 TB. Previously, this was 16 GB.

note 'CREATE TABLE': create-table. and note 'ALTER TABLE': alter-table-partition-operations. statements that would cause a user-partitioned *note 'NDB': mysql-cluster. table not to meet either or both of the following two requirements are not permitted, and fail with an error:

  1. The table must have an explicit primary key.

  2. All columns listed in the table's partitioning expression must be part of the primary key.

Exception

If a user-partitioned *note 'NDB': mysql-cluster. table is created using an empty column-list (that is, using 'PARTITION BY KEY()' or 'PARTITION BY LINEAR KEY()'), then no explicit primary key is required.

Partition selection

Partition selection is not supported for note 'NDB': mysql-cluster. tables. See note partitioning-selection::, for more information.

Upgrading partitioned tables

When performing an upgrade, tables which are partitioned by 'KEY' and which use any storage engine other than *note 'NDB': mysql-cluster. must be dumped and reloaded.

Same storage engine for all partitions

All partitions of a partitioned table must use the same storage engine and it must be the same storage engine used by the table as a whole. In addition, if one does not specify an engine on the table level, then one must do either of the following when creating or altering a partitioned table:

 File: manual.info.tmp, Node: partitioning-limitations-functions, Next: partitioning-limitations-locking, Prev: partitioning-limitations-storage-engines, Up: partitioning-limitations

22.6.3 Partitioning Limitations Relating to Functions

This section discusses limitations in MySQL Partitioning relating specifically to functions used in partitioning expressions.

Only the MySQL functions shown in the following list are allowed in partitioning expressions:

In MySQL 5.7, partition pruning is supported for the 'TO_DAYS()', 'TO_SECONDS()', 'YEAR()', and 'UNIX_TIMESTAMP()' functions. See *note partitioning-pruning::, for more information.

CEILING() and FLOOR()

Each of these functions returns an integer only if it is passed an argument of an exact numeric type, such as one of the note 'INT': integer-types. types or note 'DECIMAL': fixed-point-types. This means, for example, that the following *note 'CREATE TABLE': create-table. statement fails with an error, as shown here:

 mysql> CREATE TABLE t (c FLOAT) PARTITION BY LIST( FLOOR(c) )(
     ->     PARTITION p0 VALUES IN (1,3,5),
     ->     PARTITION p1 VALUES IN (2,4,6)
     -> );
 ERROR 1490 (HY000): The PARTITION function returns the wrong type

EXTRACT() function with WEEK specifier

The value returned by the 'EXTRACT()' function, when used as 'EXTRACT(WEEK FROM COL)', depends on the value of the 'default_week_format' system variable. For this reason, 'EXTRACT()' is not permitted as a partitioning function when it specifies the unit as 'WEEK'. (Bug #54483)

See note mathematical-functions::, for more information about the return types of these functions, as well as note numeric-types::.

 File: manual.info.tmp, Node: partitioning-limitations-locking, Prev: partitioning-limitations-functions, Up: partitioning-limitations

22.6.4 Partitioning and Locking

For storage engines such as note 'MyISAM': myisam-storage-engine. that actually execute table-level locks when executing DML or DDL statements, such a statement in older versions of MySQL (5.6.5 and earlier) that affected a partitioned table imposed a lock on the table as a whole; that is, all partitions were locked until the statement was finished. In MySQL 5.7, partition lock pruning eliminates unneeded locks in many cases, and most statements reading from or updating a partitioned 'MyISAM' table cause only the effected partitions to be locked. For example, a note 'SELECT': select. from a partitioned 'MyISAM' table locks only those partitions actually containing rows that satisfy the 'SELECT' statement's 'WHERE' condition are locked.

For statements affecting partitioned tables using storage engines such as *note 'InnoDB': innodb-storage-engine, that employ row-level locking and do not actually perform (or need to perform) the locks prior to partition pruning, this is not an issue.

The next few paragraphs discuss the effects of partition lock pruning for various MySQL statements on tables using storage engines that employ table-level locks.

Effects on DML statements

*note 'SELECT': select. statements (including those containing unions or joins) lock only those partitions that actually need to be read. This also applies to 'SELECT ... PARTITION'.

An *note 'UPDATE': update. prunes locks only for tables on which no partitioning columns are updated.

note 'REPLACE': replace. and note 'INSERT': insert. lock only those partitions having rows to be inserted or replaced. However, if an 'AUTO_INCREMENT' value is generated for any partitioning column then all partitions are locked.

*note 'INSERT ... ON DUPLICATE KEY UPDATE': insert-on-duplicate. is pruned as long as no partitioning column is updated.

*note 'INSERT ... SELECT': insert-select. locks only those partitions in the source table that need to be read, although all partitions in the target table are locked.

Locks imposed by *note 'LOAD DATA': load-data. statements on partitioned tables cannot be pruned.

The presence of 'BEFORE INSERT' or 'BEFORE UPDATE' triggers using any partitioning column of a partitioned table means that locks on 'INSERT' and 'UPDATE' statements updating this table cannot be pruned, since the trigger can alter its values: A 'BEFORE INSERT' trigger on any of the table's partitioning columns means that locks set by 'INSERT' or 'REPLACE' cannot be pruned, since the 'BEFORE INSERT' trigger may change a row's partitioning columns before the row is inserted, forcing the row into a different partition than it would be otherwise. A 'BEFORE UPDATE' trigger on a partitioning column means that locks imposed by 'UPDATE' or 'INSERT ... ON DUPLICATE KEY UPDATE' cannot be pruned.

Affected DDL statements

*note 'CREATE VIEW': create-view. does not cause any locks.

*note 'ALTER TABLE ... EXCHANGE PARTITION': alter-table-partition-operations. prunes locks; only the exchanged table and the exchanged partition are locked.

*note 'ALTER TABLE ... TRUNCATE PARTITION': alter-table-partition-operations. prunes locks; only the partitions to be emptied are locked.

In addition, *note 'ALTER TABLE': alter-table. statements take metadata locks on the table level.

Other statements

*note 'LOCK TABLES': lock-tables. cannot prune partition locks.

*note 'CALL stored_procedure(EXPR)': call. supports lock pruning, but evaluating EXPR does not.

note 'DO': do. and note 'SET': set-variable. statements do not support partitioning lock pruning.

 File: manual.info.tmp, Node: stored-objects, Next: information-schema, Prev: partitioning, Up: Top

23 Stored Objects *****************

This chapter discusses stored database objects that are defined in terms of SQL code that is stored on the server for later execution.

Stored objects include these object types:

Terminology used in this document reflects the stored object hierarchy:

This chapter describes how to use stored objects. The following sections provide additional information about SQL syntax for statements related to these objects, and about object processing:

 File: manual.info.tmp, Node: stored-programs-defining, Next: stored-routines, Prev: stored-objects, Up: stored-objects