Chapter 8 Limits in MySQL

Table of Contents

8.1 Limits on Joins
8.2 Limits on Number of Databases and Tables
8.3 Limits on Table Size
8.4 Limits on Table Column Count and Row Size
8.5 Limits Imposed by .frm File Structure
8.6 Windows Platform Limitations

This section lists current limits in MySQL 5.7.

8.1 Limits on Joins

The maximum number of tables that can be referenced in a single join is 61. This includes a join handled by merging derived tables (subqueries) and views in the FROM clause into the outer query block (see Optimizing Derived Tables and View References). It also applies to the number of tables that can be referenced in the definition of a view.

8.2 Limits on Number of Databases and Tables

MySQL has no limit on the number of databases. The underlying file system may have a limit on the number of directories.

MySQL has no limit on the number of tables. The underlying file system may have a limit on the number of files that represent tables. Individual storage engines may impose engine-specific constraints. InnoDB permits up to 4 billion tables.

8.3 Limits on Table Size

The effective maximum table size for MySQL databases is usually determined by operating system constraints on file sizes, not by MySQL internal limits. The following table lists some examples of operating system file-size limits. This is only a rough guide and is not intended to be definitive. For the most up-to-date information, be sure to check the documentation specific to your operating system.

Operating SystemFile-size Limit
Win32 w/ FAT/FAT322GB/4GB
Win32 w/ NTFS2TB (possibly larger)
Linux 2.2-Intel 32-bit2GB (LFS: 4GB)
Linux 2.4+(using ext3 file system) 4TB
Solaris 9/1016TB
OS X w/ HFS+2TB

Windows users, please note that FAT and VFAT (FAT32) are not considered suitable for production use with MySQL. Use NTFS instead.

On Linux 2.2, you can get MyISAM tables larger than 2GB in size by using the Large File Support (LFS) patch for the ext2 file system. Most current Linux distributions are based on kernel 2.4 or higher and include all the required LFS patches. On Linux 2.4, patches also exist for ReiserFS to get support for big files (up to 2TB). With JFS and XFS, petabyte and larger files are possible on Linux.

For a detailed overview about LFS in Linux, have a look at Andreas Jaeger's Large File Support in Linux page at http://www.suse.de/~aj/linux_lfs.html.

If you do encounter a full-table error, there are several reasons why it might have occurred:

  • The disk might be full.

  • The InnoDB storage engine maintains InnoDB tables within a tablespace that can be created from several files. This enables a table to exceed the maximum individual file size. The tablespace can include raw disk partitions, which permits extremely large tables. The maximum tablespace size is 64TB.

    If you are using InnoDB tables and run out of room in the InnoDB tablespace. In this case, the solution is to extend the InnoDB tablespace. See Changing the Number or Size of InnoDB Redo Log Files.

  • You are using MyISAM tables on an operating system that supports files only up to 2GB in size and you have hit this limit for the data file or index file.

  • You are using a MyISAM table and the space required for the table exceeds what is permitted by the internal pointer size. MyISAM permits data and index files to grow up to 256TB by default, but this limit can be changed up to the maximum permissible size of 65,536TB (2567 − 1 bytes).

    If you need a MyISAM table that is larger than the default limit and your operating system supports large files, the CREATE TABLE statement supports AVG_ROW_LENGTH and MAX_ROWS options. See CREATE TABLE Syntax. The server uses these options to determine how large a table to permit.

    If the pointer size is too small for an existing table, you can change the options with ALTER TABLE to increase a table's maximum permissible size. See ALTER TABLE Syntax.

    ALTER TABLE tbl_name MAX_ROWS=1000000000 AVG_ROW_LENGTH=nnn;
    

    You have to specify AVG_ROW_LENGTH only for tables with BLOB or TEXT columns; in this case, MySQL can't optimize the space required based only on the number of rows.

    To change the default size limit for MyISAM tables, set the myisam_data_pointer_size, which sets the number of bytes used for internal row pointers. The value is used to set the pointer size for new tables if you do not specify the MAX_ROWS option. The value of myisam_data_pointer_size can be from 2 to 7. A value of 4 permits tables up to 4GB; a value of 6 permits tables up to 256TB.

    You can check the maximum data and index sizes by using this statement:

    SHOW TABLE STATUS FROM db_name LIKE 'tbl_name';
    

    You also can use myisamchk -dv /path/to/table-index-file. See SHOW Syntax, or myisamchk — MyISAM Table-Maintenance Utility.

    Other ways to work around file-size limits for MyISAM tables are as follows:

    • If your large table is read only, you can use myisampack to compress it. myisampack usually compresses a table by at least 50%, so you can have, in effect, much bigger tables. myisampack also can merge multiple tables into a single table. See myisampack — Generate Compressed, Read-Only MyISAM Tables.

    • MySQL includes a MERGE library that enables you to handle a collection of MyISAM tables that have identical structure as a single MERGE table. See The MERGE Storage Engine.

  • You are using the MEMORY (HEAP) storage engine; in this case you need to increase the value of the max_heap_table_size system variable. See Server System Variables.

8.4 Limits on Table Column Count and Row Size

There is a hard limit of 4096 columns per table, but the effective maximum may be less for a given table. The exact limit depends on several interacting factors.

  • Every table (regardless of storage engine) has a maximum row size of 65,535 bytes. Storage engines may place additional constraints on this limit, reducing the effective maximum row size.

    The maximum row size constrains the number (and possibly size) of columns because the total length of all columns cannot exceed this size. For example, utf8 characters require up to three bytes per character, so for a CHAR(255) CHARACTER SET utf8 column, the server must allocate 255 × 3 = 765 bytes per value. Consequently, a table cannot contain more than 65,535 / 765 = 85 such columns.

    Storage for variable-length columns includes length bytes, which are assessed against the row size. For example, a VARCHAR(255) CHARACTER SET utf8 column takes two bytes to store the length of the value, so each value can take up to 767 bytes.

    BLOB and TEXT columns count from one to four plus eight bytes each toward the row-size limit because their contents are stored separately from the rest of the row.

    Declaring columns NULL can reduce the maximum number of columns permitted. For MyISAM tables, NULL columns require additional space in the row to record whether their values are NULL. Each NULL column takes one bit extra, rounded up to the nearest byte. The maximum row length in bytes can be calculated as follows:

    row length = 1
                 + (sum of column lengths)
                 + (number of NULL columns + delete_flag + 7)/8
                 + (number of variable-length columns)
    

    delete_flag is 1 for tables with static row format. Static tables use a bit in the row record for a flag that indicates whether the row has been deleted. delete_flag is 0 for dynamic tables because the flag is stored in the dynamic row header. For information about MyISAM table formats, see MyISAM Table Storage Formats.

    For InnoDB tables, storage size is the same for NULL and NOT NULL columns, so the preceding calculations do not apply.

    The following statement to create table t1 succeeds because the columns require 32,765 + 2 bytes and 32,766 + 2 bytes, which falls within the maximum row size of 65,535 bytes:

    mysql> CREATE TABLE t1
        -> (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
        -> ENGINE = MyISAM CHARACTER SET latin1;
    Query OK, 0 rows affected (0.02 sec)
    

    The following statement to create table t2 fails because the columns are NULL and MyISAM requires additional space that causes the row size to exceed 65,535 bytes:

    mysql> CREATE TABLE t2
        -> (c1 VARCHAR(32765) NULL, c2 VARCHAR(32766) NULL)
        -> ENGINE = MyISAM CHARACTER SET latin1;
    ERROR 1118 (42000): Row size too large. The maximum row size for the
    used table type, not counting BLOBs, is 65535. You have to change some
    columns to TEXT or BLOBs
    

    The following statement to create table t3 fails because, although the column length is within the maximum length of 65,535 bytes, two additional bytes are required to record the length, which causes the row size to exceed 65,535 bytes:

    mysql> CREATE TABLE t3
        -> (c1 VARCHAR(65535) NOT NULL)
        -> ENGINE = MyISAM CHARACTER SET latin1;
    ERROR 1118 (42000): Row size too large. The maximum row size for the
    used table type, not counting BLOBs, is 65535. You have to change some
    columns to TEXT or BLOBs
    

    Reducing the column length to 65,533 or less permits the statement to succeed.

  • Individual storage engines might impose additional restrictions that limit table column count. Examples:

    • InnoDB permits up to 1000 columns.

    • InnoDB restricts row size to slightly less than half of a database page for 4KB, 8KB, 16KB, and 32KB page sizes. For a page size of 64KB, InnoDB restricts row size to about 16000 bytes. Row size restrictions differ for variable-length columns (VARBINARY, VARCHAR, BLOB, and TEXT). For more information, see Limits on InnoDB Tables.

    • Different InnoDB storage formats (COMPRESSED, REDUNDANT) use different amounts of page header and trailer data, which affects the amount of storage available for rows.

8.5 Limits Imposed by .frm File Structure

Each table has an .frm file that contains the table definition. The server uses the following expression to check some of the table information stored in the file against an upper limit of 64KB:

if (info_length+(ulong) create_fields.elements*FCOMP+288+
    n_length+int_length+com_length > 65535L || int_count > 255)

The portion of the information stored in the .frm file that is checked against the expression cannot grow beyond the 64KB limit, so if the table definition reaches this size, no more columns can be added.

The relevant factors in the expression are:

  • info_length is space needed for screens. This is related to MySQL's Unireg heritage.

  • create_fields.elements is the number of columns.

  • FCOMP is 17.

  • n_length is the total length of all column names, including one byte per name as a separator.

  • int_length is related to the list of values for ENUM and SET columns. In this context, int does not mean integer. It means interval, a term that refers collectively to ENUM and SET columns.

  • int_count is the number of unique ENUM and SET definitions.

  • com_length is the total length of column comments.

The expression just described has several implications for permitted table definitions:

  • Using long column names can reduce the maximum number of columns, as can the inclusion of ENUM or SET columns, or use of column comments.

  • A table can have no more than 255 unique ENUM and SET definitions. Columns with identical element lists are considered the same against this limt. For example, if a table contains these two columns, they count as one (not two) toward this limit because the definitions are identical:

    e1 ENUM('a','b','c')
    e2 ENUM('a','b','c')
    
  • The sum of the length of element names in the unique ENUM and SET definitions counts toward the 64KB limit, so although the theoretical limit on number of elements in a given ENUM column is 65,535, the practical limit is less than 3000.

8.6 Windows Platform Limitations

The following limitations apply to use of MySQL on the Windows platform:

  • Process memory

    On Windows 32-bit platforms, it is not possible by default to use more than 2GB of RAM within a single process, including MySQL. This is because the physical address limit on Windows 32-bit is 4GB and the default setting within Windows is to split the virtual address space between kernel (2GB) and user/applications (2GB).

    Some versions of Windows have a boot time setting to enable larger applications by reducing the kernel application. Alternatively, to use more than 2GB, use a 64-bit version of Windows.

  • File system aliases

    When using MyISAM tables, you cannot use aliases within Windows link to the data files on another volume and then link back to the main MySQL datadir location.

    This facility is often used to move the data and index files to a RAID or other fast solution, while retaining the main .frm files in the default data directory configured with the datadir option.

  • Limited number of ports

    Windows systems have about 4,000 ports available for client connections, and after a connection on a port closes, it takes two to four minutes before the port can be reused. In situations where clients connect to and disconnect from the server at a high rate, it is possible for all available ports to be used up before closed ports become available again. If this happens, the MySQL server appears to be unresponsive even though it is running. Ports may be used by other applications running on the machine as well, in which case the number of ports available to MySQL is lower.

    For more information about this problem, see http://support.microsoft.com/default.aspx?scid=kb;en-us;196271.

  • DATA DIRECTORY and INDEX DIRECTORY

    The DATA DIRECTORY option for CREATE TABLE is supported on Windows only for InnoDB tables, as described in Creating a File-Per-Table Tablespace Outside the Data Directory. For MyISAM and other storage engines, the DATA DIRECTORY and INDEX DIRECTORY options for CREATE TABLE are ignored on Windows and any other platforms with a nonfunctional realpath() call.

  • DROP DATABASE

    You cannot drop a database that is in use by another session.

  • Case-insensitive names

    File names are not case sensitive on Windows, so MySQL database and table names are also not case sensitive on Windows. The only restriction is that database and table names must be specified using the same case throughout a given statement. See Identifier Case Sensitivity.

  • Directory and file names

    On Windows, MySQL Server supports only directory and file names that are compatible with the current ANSI code pages. For example, the following Japanese directory name will not work in the Western locale (code page 1252):

    datadir="C:/私たちのプロジェクトのデータ"
    

    The same limitation applies to directory and file names referred to in SQL statements, such as the data file path name in LOAD DATA INFILE.

  • The \ path name separator character

    Path name components in Windows are separated by the \ character, which is also the escape character in MySQL. If you are using LOAD DATA INFILE or SELECT ... INTO OUTFILE, use Unix-style file names with / characters:

    mysql> LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr;
    mysql> SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
    

    Alternatively, you must double the \ character:

    mysql> LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr;
    mysql> SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
    
  • Problems with pipes

    Pipes do not work reliably from the Windows command-line prompt. If the pipe includes the character ^Z / CHAR(24), Windows thinks that it has encountered end-of-file and aborts the program.

    This is mainly a problem when you try to apply a binary log as follows:

    C:\> mysqlbinlog binary_log_file | mysql --user=root
    

    If you have a problem applying the log and suspect that it is because of a ^Z / CHAR(24) character, you can use the following workaround:

    C:\> mysqlbinlog binary_log_file --result-file=/tmp/bin.sql
    C:\> mysql --user=root --execute "source /tmp/bin.sql"
    

    The latter command also can be used to reliably read in any SQL file that may contain binary data.