CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEX index_name
[index_type]
ON tbl_name (key_part,...)
[index_option]
[algorithm_option | lock_option] ...
key_part:
col_name [(length)] [ASC | DESC]
index_option: {
KEY_BLOCK_SIZE [=] value
| index_type
| WITH PARSER parser_name
| COMMENT 'string'
}
index_type:
USING {BTREE | HASH}
algorithm_option:
ALGORITHM [=] {DEFAULT | INPLACE | COPY}
lock_option:
LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
Normally, you create all indexes on a table at the time the table
itself is created with CREATE
TABLE. See Section 13.1.18, “CREATE TABLE Statement”. This
guideline is especially important for
InnoDB tables, where the primary key
determines the physical layout of rows in the data file.
CREATE INDEX enables you to add
indexes to existing tables.
CREATE INDEX is mapped to an
ALTER TABLE statement to create
indexes. See Section 13.1.8, “ALTER TABLE Statement”.
CREATE INDEX cannot be used to
create a PRIMARY KEY; use
ALTER TABLE instead. For more
information about indexes, see Section 8.3.1, “How MySQL Uses Indexes”.
InnoDB supports secondary indexes on
virtual columns. For more information, see
Section 13.1.18.8, “Secondary Indexes and Generated Columns”.
When the innodb_stats_persistent
setting is enabled, run the ANALYZE
TABLE statement for an
InnoDB table after creating an index
on that table.
An index specification of the form
( creates an
index with multiple key parts. Index key values are formed by
concatenating the values of the given key parts. For example
key_part1,
key_part2, ...)(col1, col2, col3) specifies a multiple-column
index with index keys consisting of values from
col1, col2, and
col3.
A key_part specification can end with
ASC or DESC. These keywords
are permitted for future extensions for specifying ascending or
descending index value storage. Currently, they are parsed but
ignored; index values are always stored in ascending order.
The following sections describe different aspects of the
CREATE INDEX statement:
For string columns, indexes can be created that use only the
leading part of column values, using
syntax to specify an index prefix length:
col_name(length)
Prefixes can be specified for
CHAR,VARCHAR,BINARY, andVARBINARYkey parts.Prefixes must be specified for
BLOBandTEXTkey parts. Additionally,BLOBandTEXTcolumns can be indexed only forInnoDB,MyISAM, andBLACKHOLEtables.Prefix limits are measured in bytes. However, prefix lengths for index specifications in
CREATE TABLE,ALTER TABLE, andCREATE INDEXstatements are interpreted as number of characters for nonbinary string types (CHAR,VARCHAR,TEXT) and number of bytes for binary string types (BINARY,VARBINARY,BLOB). Take this into account when specifying a prefix length for a nonbinary string column that uses a multibyte character set.Prefix support and lengths of prefixes (where supported) are storage engine dependent. For example, a prefix can be up to 767 bytes long for
InnoDBtables or 3072 bytes if theinnodb_large_prefixoption is enabled. ForMyISAMtables, the prefix length limit is 1000 bytes. TheNDBstorage engine does not support prefixes (see Section 21.2.7.6, “Unsupported or Missing Features in NDB Cluster”).
As of MySQL 5.7.17, if a specified index prefix exceeds the
maximum column data type size, CREATE
INDEX handles the index as follows:
For a nonunique index, either an error occurs (if strict SQL mode is enabled), or the index length is reduced to lie within the maximum column data type size and a warning is produced (if strict SQL mode is not enabled).
For a unique index, an error occurs regardless of SQL mode because reducing the index length might enable insertion of nonunique entries that do not meet the specified uniqueness requirement.
The statement shown here creates an index using the first 10
characters of the name column (assuming that
name has a nonbinary string type):
CREATE INDEX part_of_name ON customer (name(10));
If names in the column usually differ in the first 10
characters, lookups performed using this index should not be
much slower than using an index created from the entire
name column. Also, using column prefixes for
indexes can make the index file much smaller, which could save a
lot of disk space and might also speed up
INSERT operations.
A UNIQUE index creates a constraint such that
all values in the index must be distinct. An error occurs if you
try to add a new row with a key value that matches an existing
row. If you specify a prefix value for a column in a
UNIQUE index, the column values must be
unique within the prefix length. A UNIQUE
index permits multiple NULL values for
columns that can contain NULL.
If a table has a PRIMARY KEY or
UNIQUE NOT NULL index that consists of a
single column that has an integer type, you can use
_rowid to refer to the indexed column in
SELECT statements, as follows:
_rowidrefers to thePRIMARY KEYcolumn if there is aPRIMARY KEYconsisting of a single integer column. If there is aPRIMARY KEYbut it does not consist of a single integer column,_rowidcannot be used.Otherwise,
_rowidrefers to the column in the firstUNIQUE NOT NULLindex if that index consists of a single integer column. If the firstUNIQUE NOT NULLindex does not consist of a single integer column,_rowidcannot be used.
FULLTEXT indexes are supported only for
InnoDB and
MyISAM tables and can include only
CHAR,
VARCHAR, and
TEXT columns. Indexing always
happens over the entire column; column prefix indexing is not
supported and any prefix length is ignored if specified. See
Section 12.9, “Full-Text Search Functions”, for details of operation.
The MyISAM,
InnoDB,
NDB, and
ARCHIVE storage engines support
spatial columns such as POINT and
GEOMETRY.
(Section 11.4, “Spatial Data Types”, describes the spatial data
types.) However, support for spatial column indexing varies
among engines. Spatial and nonspatial indexes on spatial columns
are available according to the following rules.
Spatial indexes on spatial columns (created using
SPATIAL INDEX) have these characteristics:
Nonspatial indexes on spatial columns (created with
INDEX, UNIQUE, or
PRIMARY KEY) have these characteristics:
Permitted for any storage engine that supports spatial columns except
ARCHIVE.Columns can be
NULLunless the index is a primary key.For each spatial column in a non-
SPATIALindex exceptPOINTcolumns, a column prefix length must be specified. (This is the same requirement as for indexedBLOBcolumns.) The prefix length is given in bytes.The index type for a non-
SPATIALindex depends on the storage engine. Currently, B-tree is used.Permitted for a column that can have
NULLvalues only forInnoDB,MyISAM, andMEMORYtables.
Following the key part list, index options can be given. An
index_option value can be any of the
following:
KEY_BLOCK_SIZE [=]valueFor
MyISAMtables,KEY_BLOCK_SIZEoptionally specifies the size in bytes to use for index key blocks. The value is treated as a hint; a different size could be used if necessary. AKEY_BLOCK_SIZEvalue specified for an individual index definition overrides a table-levelKEY_BLOCK_SIZEvalue.KEY_BLOCK_SIZEis not supported at the index level forInnoDBtables. See Section 13.1.18, “CREATE TABLE Statement”.index_typeSome storage engines permit you to specify an index type when creating an index. For example:
CREATE TABLE lookup (id INT) ENGINE = MEMORY; CREATE INDEX id_index ON lookup (id) USING BTREE;Table 13.1, “Index Types Per Storage Engine” shows the permissible index type values supported by different storage engines. Where multiple index types are listed, the first one is the default when no index type specifier is given. Storage engines not listed in the table do not support an
index_typeclause in index definitions.The
index_typeclause cannot be used forFULLTEXT INDEXorSPATIAL INDEXspecifications. Full-text index implementation is storage engine dependent. Spatial indexes are implemented as R-tree indexes.BTREEindexes are implemented by theNDBstorage engine as T-tree indexes.NoteFor indexes on
NDBtable columns, theUSINGoption can be specified only for a unique index or primary key.USING HASHprevents the creation of an ordered index; otherwise, creating a unique index or primary key on anNDBtable automatically results in the creation of both an ordered index and a hash index, each of which indexes the same set of columns.For unique indexes that include one or more
NULLcolumns of anNDBtable, the hash index can be used only to look up literal values, which means thatIS [NOT] NULLconditions require a full scan of the table. One workaround is to make sure that a unique index using one or moreNULLcolumns on such a table is always created in such a way that it includes the ordered index; that is, avoid employingUSING HASHwhen creating the index.If you specify an index type that is not valid for a given storage engine, but another index type is available that the engine can use without affecting query results, the engine uses the available type. The parser recognizes
RTREEas a type name, but currently this cannot be specified for any storage engine.NoteUse of the
index_typeoption before theONclause is deprecated; you should expect support for use of the option in this position to be removed in a future MySQL release. If antbl_nameindex_typeoption is given in both the earlier and later positions, the final option applies.TYPEis recognized as a synonym fortype_nameUSING. However,type_nameUSINGis the preferred form.The following tables show index characteristics for the storage engines that support the
index_typeoption.Table 13.2 InnoDB Storage Engine Index Characteristics
Index Class Index Type Stores NULL VALUES Permits Multiple NULL Values IS NULL Scan Type IS NOT NULL Scan Type Primary key BTREENo No N/A N/A Unique BTREEYes Yes Index Index Key BTREEYes Yes Index Index FULLTEXTN/A Yes Yes Table Table SPATIALN/A No No N/A N/A
Table 13.3 MyISAM Storage Engine Index Characteristics
Index Class Index Type Stores NULL VALUES Permits Multiple NULL Values IS NULL Scan Type IS NOT NULL Scan Type Primary key BTREENo No N/A N/A Unique BTREEYes Yes Index Index Key BTREEYes Yes Index Index FULLTEXTN/A Yes Yes Table Table SPATIALN/A No No N/A N/A
Table 13.4 MEMORY Storage Engine Index Characteristics
Index Class Index Type Stores NULL VALUES Permits Multiple NULL Values IS NULL Scan Type IS NOT NULL Scan Type Primary key BTREENo No N/A N/A Unique BTREEYes Yes Index Index Key BTREEYes Yes Index Index Primary key HASHNo No N/A N/A Unique HASHYes Yes Index Index Key HASHYes Yes Index Index
Table 13.5 NDB Storage Engine Index Characteristics
Index Class Index Type Stores NULL VALUES Permits Multiple NULL Values IS NULL Scan Type IS NOT NULL Scan Type Primary key BTREENo No Index Index Unique BTREEYes Yes Index Index Key BTREEYes Yes Index Index Primary key HASHNo No Table (see note 1) Table (see note 1) Unique HASHYes Yes Table (see note 1) Table (see note 1) Key HASHYes Yes Table (see note 1) Table (see note 1) Table note:
1. If
USING HASHis specified that prevents creation of an implicit ordered index.WITH PARSERparser_nameThis option can be used only with
FULLTEXTindexes. It associates a parser plugin with the index if full-text indexing and searching operations need special handling.InnoDBandMyISAMsupport full-text parser plugins. If you have aMyISAMtable with an associated full-text parser plugin, you can convert the table toInnoDBusingALTER TABLE. See Full-Text Parser Plugins and Writing Full-Text Parser Plugins for more information.COMMENT 'string'Index definitions can include an optional comment of up to 1024 characters.
The
MERGE_THRESHOLDfor index pages can be configured for individual indexes using theindex_optionCOMMENTclause of theCREATE INDEXstatement. For example:CREATE TABLE t1 (id INT); CREATE INDEX id_index ON t1 (id) COMMENT 'MERGE_THRESHOLD=40';If the page-full percentage for an index page falls below the
MERGE_THRESHOLDvalue when a row is deleted or when a row is shortened by an update operation,InnoDBattempts to merge the index page with a neighboring index page. The defaultMERGE_THRESHOLDvalue is 50, which is the previously hardcoded value.MERGE_THRESHOLDcan also be defined at the index level and table level usingCREATE TABLEandALTER TABLEstatements. For more information, see Section 14.8.12, “Configuring the Merge Threshold for Index Pages”.
ALGORITHM and LOCK clauses
may be given to influence the table copying method and level of
concurrency for reading and writing the table while its indexes
are being modified. They have the same meaning as for the
ALTER TABLE statement. For more
information, see Section 13.1.8, “ALTER TABLE Statement”
NDB Cluster formerly supported online CREATE
INDEX operations using an alternative syntax that is
no longer supported. NDB Cluster now supports online operations
using the same ALGORITHM=INPLACE syntax used
with the standard MySQL Server. See
Section 21.6.12, “Online Operations with ALTER TABLE in NDB Cluster”, for more
information.