## 24.6 Restrictions and Limitations on Partitioning

[24.6.1 Partitioning Keys, Primary Keys, and Unique Keys](partitioning-limitations-partitioning-keys-unique-keys.html)
[24.6.2 Partitioning Limitations Relating to Storage Engines](partitioning-limitations-storage-engines.html)
[24.6.3 Partitioning Limitations Relating to Functions](partitioning-limitations-functions.html)

[]()

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

**Prohibited constructs.**  The following constructs are not permitted in partitioning expressions:

* Stored procedures, stored functions, loadable functions, or plugins.

* Declared variables or user variables.

 For a list of SQL functions which are permitted in partitioning expressions, see [Section 24.6.3, “Partitioning Limitations Relating to Functions”](partitioning-limitations-functions.html).

**Arithmetic and logical operators.**  []() []() Use of the arithmetic operators [`+`](arithmetic-functions.html#operator_plus), [`-`](arithmetic-functions.html#operator_minus), and [`*`](arithmetic-functions.html#operator_times) 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 [Section 24.2, “Partitioning Types”](partitioning-types.html), for more information).

 The [`DIV`](arithmetic-functions.html#operator_div) operator is also supported; the [`/`](arithmetic-functions.html#operator_divide) operator is not permitted.

 The bit operators [`|`](bit-functions.html#operator_bitwise-or), [`&`](bit-functions.html#operator_bitwise-and), [`^`](bit-functions.html#operator_bitwise-xor), [`<<`](bit-functions.html#operator_left-shift), [`>>`](bit-functions.html#operator_right-shift), and [`~`](bit-functions.html#operator_bitwise-invert) are not permitted in partitioning expressions.

**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 elsewhere in this Manual (see [Section 5.1.11, “Server SQL Modes”](sql-mode.html)), 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*.

 For one such change in the server SQL mode making a partitioned tables unusable, consider the following [`CREATE TABLE`](create-table.html) statement, which can be executed successfully only if the [`NO_UNSIGNED_SUBTRACTION`](sql-mode.html#sqlmode_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`](sql-mode.html#sqlmode_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 [Section 5.1.11, “Server SQL Modes”](sql-mode.html).

 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:

* []()**File system operations.**  Partitioning and repartitioning operations (such as [`ALTER TABLE`](alter-table-partition-operations.html) with `PARTITION BY ...`, `REORGANIZE PARTITION`, or `REMOVE PARTITIONING`) depend on file system operations for their implementation. This means that the speed of these operations is affected by such factors as file system type and characteristics, disk speed, swap space, file handling efficiency of the operating system, and MySQL server options and variables that relate to file handling. In particular, you should make sure that [`large_files_support`](server-system-variables.html#sysvar_large_files_support) is enabled and that [`open_files_limit`](server-system-variables.html#sysvar_open_files_limit) is set properly. Partitioning and repartitioning operations involving `InnoDB` tables may be made more efficient by enabling [`innodb_file_per_table`](innodb-parameters.html#sysvar_innodb_file_per_table).

   See also [Maximum number of partitions](partitioning-limitations.html#partitioning-limitations-max-partitions).

* **Table locks.**  Generally, the process executing a partitioning operation on a table takes a write lock on the table. Reads from such tables are relatively unaffected; pending [`INSERT`](insert.html) and [`UPDATE`](update.html) operations are performed as soon as the partitioning operation has completed. For `InnoDB`-specific exceptions to this limitation, see [Partitioning Operations](innodb-online-ddl-operations.html#online-ddl-partitioning).

* **Indexes; partition pruning.**  As with nonpartitioned tables, proper use of indexes can speed up queries on partitioned tables significantly. In addition, designing partitioned tables and queries on these tables to take advantage of partition pruning can improve performance dramatically. See [Section 24.4, “Partition Pruning”](partitioning-pruning.html), for more information.

   Index condition pushdown is supported for partitioned tables. See [Section 8.2.1.6, “Index Condition Pushdown Optimization”](index-condition-pushdown-optimization.html).

* **Performance with LOAD DATA.**  In MySQL 8.0, [`LOAD DATA`](load-data.html) uses buffering to improve performance. You should be aware that the buffer uses 130 KB memory per partition to achieve this.

[]()**Maximum number of partitions.** []()[]() The maximum possible number of partitions for a given table not using the [`NDB`](mysql-cluster.html) storage engine is 8192. This number includes subpartitions.

 The maximum possible number of user-defined partitions for a table using the [`NDB`](mysql-cluster.html) storage engine is determined according to the version of the NDB Cluster software being used, the number of data nodes, and other factors. See [NDB and user-defined partitioning](mysql-cluster-nodes-groups.html#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`](server-system-variables.html#sysvar_open_files_limit) system variable. However, this is dependent on the operating system, and may not be possible or advisable on all platforms; see [Section B.3.2.16, “File Not Found and Similar Errors”](not-enough-file-handles.html), 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 [File system operations](partitioning-limitations.html#partitioning-limitations-file-system-ops).

**Foreign keys not supported for partitioned InnoDB tables.** []() Partitioned tables using the [`InnoDB`](innodb-storage-engine.html) 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. [`CREATE TABLE`](create-table-foreign-keys.html) and [`ALTER TABLE`](alter-table.html) 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.

**ADD COLUMN ... ALGORITHM=INSTANT.**  Once you perform [`ALTER TABLE ... ADD COLUMN ... ALGORITHM=INSTANT`](alter-table.html) on a partitioned table, it is no longer possible to exchange partitions with this table.

**Effects on REPLACE statements by modification of primary keys.**  It can be desirable in some cases (see [Section 24.6.1, “Partitioning Keys, Primary Keys, and Unique Keys”](partitioning-limitations-partitioning-keys-unique-keys.html)) to modify a table's primary key. Be aware that, if your application uses [`REPLACE`](replace.html) statements and you do this, the results of these statements can be drastically altered. See [Section 13.2.9, “REPLACE Statement”](replace.html), for more information and an example.

**FULLTEXT indexes.** []() Partitioned tables do not support `FULLTEXT` indexes or searches.

**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.

**Log tables.**  It is not possible to partition the log tables; an [`ALTER TABLE ... PARTITION BY ...`](alter-table-partition-operations.html) 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 [`ENUM`](enum.html) columns cannot be used. The column or expression value may also be `NULL`; see [Section 24.2.7, “How MySQL Partitioning Handles NULL”](partitioning-handling-nulls.html).

 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 [`TEXT`](blob.html) or [`BLOB`](blob.html) as partitioning keys, because the internal key-hashing functions produce the correct data type from these types. For example, the following two [`CREATE TABLE`](create-table.html) 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, [`DATE`](datetime.html), and [`DATETIME`](datetime.html) columns. For example, each of the following [`CREATE TABLE`](create-table.html) 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 [`BLOB`](blob.html) or [`TEXT`](blob.html) 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 [`CREATE TABLE`](create-table.html) statement, which has three [`VARCHAR`](char.html) 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;
```

 Prior to MySQL 8.0.21, no warning was issued or any other indication provided that this occurred, except in the event that all columns specified for the partitioning key used prefixes, in which case the statement failed, but with a misleading error message, as 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 occured when performing [`ALTER TABLE`](alter-table.html) or when upgrading such tables.

 This permissive behavior is deprecated as of MySQL 8.0.21 (and is subject to removal in a future version of MySQL). Beginning with MySQL 8.0.21, using one or more columns having a prefix in the partitioning key results in a warning for each such column, as shown here:

```
mysql> CREATE TABLE t1 (
    ->     a VARCHAR(10000),
    ->     b VARCHAR(25),
    ->     c VARCHAR(10),
    ->     PRIMARY KEY (a(10), b, c(2))
    -> ) PARTITION BY KEY() PARTITIONS 2;
Query OK, 0 rows affected, 2 warnings (1.25 sec)

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Warning
   Code: 1681
Message: Column 'test.t1.a' having prefix key part 'a(10)' is ignored by the
partitioning function. Use of prefixed columns in the PARTITION BY KEY() clause
is deprecated and will be removed in a future release.
*************************** 2. row ***************************
  Level: Warning
   Code: 1681
Message: Column 'test.t1.c' having prefix key part 'c(2)' is ignored by the
partitioning function. Use of prefixed columns in the PARTITION BY KEY() clause
is deprecated and will be removed in a future release.
2 rows in set (0.00 sec)
```

 This 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.

 In MySQL 8.0.21 and later, if all columns specified for the partitioning key employ prefixes, the `CREATE TABLE` statement used fails with an error message that identifies the issue correctly:

```
mysql> CREATE TABLE t1 (
    ->     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 (prefixed columns are not considered).
```

 For general information about partitioning tables by key, see [Section 24.2.5, “KEY Partitioning”](partitioning-key.html).

[]()**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.**  Table-level `DATA DIRECTORY` and `INDEX DIRECTORY` options are ignored (see Bug #32091). You can employ these options for individual partitions or subpartitions of [`InnoDB`](innodb-storage-engine.html) tables. As of MySQL 8.0.21, the directory specified in a `DATA DIRECTORY` clause must be known to `InnoDB`. For more information, see [Using the DATA DIRECTORY Clause](innodb-create-table-external.html#innodb-create-table-external-data-directory).

**Repairing and rebuilding partitioned tables.**  The statements [`CHECK TABLE`](check-table.html), [`OPTIMIZE TABLE`](optimize-table.html), [`ANALYZE TABLE`](analyze-table.html), and [`REPAIR TABLE`](repair-table.html) 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 [Section 13.1.9, “ALTER TABLE Statement”](alter-table.html), for more information about these two statements.

`ANALYZE`, `CHECK`, `OPTIMIZE`, `REPAIR`, and `TRUNCATE` operations are supported with subpartitions. See [Section 13.1.9.1, “ALTER TABLE Partition Operations”](alter-table-partition-operations.html).

**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.

