CREATE [UNIQUE | FULLTEXT | SPATIAL] INDEXindex_name[index_type] ONtbl_name(key_part,...) [index_option] [algorithm_option|lock_option] ...key_part: {col_name[(length)] | (expr)} [ASC | DESC]index_option: { KEY_BLOCK_SIZE [=]value|index_type| WITH PARSERparser_name| COMMENT 'string' | {VISIBLE | INVISIBLE} | ENGINE_ATTRIBUTE [=] 'string' | SECONDARY_ENGINE_ATTRIBUTE [=] 'string' }index_type: USING {BTREE | HASH}algorithm_option: ALGORITHM [=] {DEFAULT | INPLACE | COPY}lock_option: LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
通常,在创建表时创建所有索引,使用 CREATE
TABLE。参见 第 15.1.20 节,“CREATE TABLE Statement”。该指南对于 InnoDB,其中主键决定数据文件行的物理布局。CREATE INDEX为现有表添加索引。Normally, you create all indexes on a table at the time the table
itself is created with CREATE
TABLE. See Section 15.1.20, “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 映射到 ALTER TABLE 语句用于创建索引。参见 第 15.1.9 节,”ALTER TABLE Statement“。CREATE INDEX 不能用于创建 PRIMARY KEY使用 ALTER TABLE“。有关索引的更多信息,请参见 第 10.3.1 节,”MySQL 如何使用索引“。CREATE INDEX is mapped to an
ALTER TABLE statement to create
indexes. See Section 15.1.9, “ALTER TABLE Statement”.
CREATE INDEX cannot be used to
create a PRIMARY KEY; use
ALTER TABLE instead. For more
information about indexes, see Section 10.3.1, “How MySQL Uses Indexes”.
InnoDB支持虚拟列的二级索引。更多信息请参见 第 15.1.20.9 节,“次级索引和生成列”。InnoDB supports secondary indexes on
virtual columns. For more information, see
Section 15.1.20.9, “Secondary Indexes and Generated Columns”.
当启用 innodb_stats_persistent 设置时,在创建索引后运行 ANALYZE
TABLE 语句,InnoDB 表,并在该表上创建索引。When the innodb_stats_persistent
setting is enabled, run the ANALYZE
TABLE statement for an
InnoDB table after creating an index
on that table.
该expr for a
key_part specification can also take
the form (CAST to create a
multi-valued index on a json_expression
AS type ARRAY)JSON
column. See Multi-Valued Indexes.The expr for a
key_part specification can also take
the form (CAST to create a
multi-valued index on a json_expression
AS type ARRAY)JSON
column. See Multi-Valued Indexes.
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,以及col3.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或者DESC to specify
whether index values are stored in ascending or descending order.
The default is ascending if no order specifier is given.A key_part specification can end with
ASC or DESC to specify
whether index values are stored in ascending or descending order.
The default is ascending if no order specifier is given.
ASC 和 DESC 不支持 HASH 索引、多值索引或 SPATIAL 索引。ASC and DESC are not
supported for HASH indexes, multi-valued
indexes or SPATIAL indexes.
以下章节描述了CREATE INDEX 语句: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
col_name(length)
syntax to specify an index prefix length:col_name(length)
前缀可以指定为
CHAR,VARCHAR,BINARYandVARBINARYkey parts.Prefixes can be specified forCHAR,VARCHAR,BINARY, andVARBINARYkey parts.前缀 必须为
BLOB和TEXT键部分。此外,BLOB和TEXT列只能索引InnoDB,MyISAM,BLACKHOLE表。Prefixes must be specified forBLOBandTEXTkey parts. Additionally,BLOBandTEXTcolumns can be indexed only forInnoDB,MyISAM, andBLACKHOLEtables.前缀 限制以字节为单位。然而,索引规范前缀 lengths 用于
CREATE TABLE“,ALTER TABLE”,CREATE INDEX语句被解释为非二元字符串类型的字符数(CHARVARCHAR,TEXT以及二进制字符串的字节数类型 (BINARY,VARBINARYBLOB)。在为使用多字节字符集的非二元字符串列指定前缀长度时,请考虑这一点。Prefix limits are measured in bytes. However, prefix lengths for index specifications inCREATE 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.前缀支持及前缀长度(如支持)依赖于存储引擎。例如,对于使用
REDUNDANT或COMPACT行格式的InnoDB表,前缀最长可达 767 字节。对于使用DYNAMIC或COMPRESSED行格式的InnoDB表,前缀长度限制为 3072 字节。对于MyISAM表,前缀长度限制为 1000 字节。NDB存储引擎不支持前缀(见 第 25.2.7.6 节,“NDB Cluster 中不支持或缺失的功能”)。Prefix support and lengths of prefixes (where supported) are storage engine dependent. For example, a prefix can be up to 767 bytes long forInnoDBtables that use theREDUNDANTorCOMPACTrow format. The prefix length limit is 3072 bytes forInnoDBtables that use theDYNAMICorCOMPRESSEDrow format. ForMyISAMtables, the prefix length limit is 1000 bytes. TheNDBstorage engine does not support prefixes (see Section 25.2.7.6, “Unsupported or Missing Features in NDB Cluster”).
如果指定的索引前缀超过了最大列数据类型的大小,CREATE INDEX 将按照以下方式处理索引:If a specified index prefix exceeds the maximum column data type
size, CREATE INDEX handles the
index as follows:
对于非唯一索引,如果启用了严格 SQL 模式,则会发生错误;如果未启用严格 SQL 模式,则索引长度会被缩减到不超过最大列数据类型的大小,并会产生警告。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).
对于唯一索引,无论 SQL 模式如何,都会发生错误,因为缩短索引长度可能会允许插入不符合指定唯一性要求的非唯一条目。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.
此处显示的语句创建了一个索引,使用 name 列的前 10 个字符(假设 name 是非二进制字符串类型):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));
如果列中的姓名通常在前 10 个字符就不同,那么使用此索引执行的查找操作应该不会比使用整个 name 列创建的索引慢太多。此外,为索引使用列前缀可以使索引文件更小,这可能节省大量磁盘空间,还可能加快 INSERT 操作的速度。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 “普通”索引索引列值或列值的前缀。例如,在下表中,给定t1行的索引条目包括完整的col1值以及由值的前 10 个字符组成的前缀:col2解决方案 1. 将索引表达式分配相同的排序规则为A “normal” index indexes column values or prefixes
of column values. For example, in the following table, the index
entry for a given t1 row includes the full
col1 value and a prefix of the
col2 value consisting of its first 10
characters:
CREATE TABLE t1 ( col1 VARCHAR(10), col2 VARCHAR(20), INDEX (col1, col2(10)) );
用于索引表达式值的函数键部分也可以用来代替列或列前缀值。使用函数键部分可以对表中未直接存储的值进行索引。例如:Functional key parts that index expression values canalso be used in place of column or column prefix values. Use of functional key parts enables indexing of values not stored directly in the table. Examples:
CREATE TABLE t1 (col1 INT, col2 INT, INDEX func_index ((ABS(col1)))); CREATE INDEX idx1 ON t1 ((col1 + col2)); CREATE INDEX idx2 ON t1 ((col1 + col2), (col1 - col2), col1); ALTER TABLE t1 ADD INDEX ((col1 * 40) DESC);
具有多个键部分的索引可以混合使用非函数键部分和函数键部分。An index with multiple key parts can mix nonfunctional and functional key parts.
ASC 和 DESC 支持用于功能键部分。ASC and DESC are supported
for functional key parts.
功能键部分必须遵守以下规则。如果键部分定义包含不允许的结构,将会发生错误。Functional key parts must adhere to the following rules. An error occurs if a key part definition contains disallowed constructs.
在索引定义中,应将表达式括在括号内,以便将其与列或列前缀区分开来。例如,这是允许的;表达式被括在括号内:In index definitions, enclose expressions within parentheses to distinguish them from columns or column prefixes. For example, this is permitted; the expressions are enclosed within parentheses:
INDEX ((col1 + col2), (col3 - col4))
这会产生错误;表达式没有括在括号内:This produces an error; the expressions are not enclosed within parentheses:
INDEX (col1 + col2, col3 - col4)
功能键部分不能仅由列名组成。例如,这是不允许的:A functional key part cannot consist solely of a column name. For example, this is not permitted:
INDEX ((col1), (col2))
相反,应将键部分写为非功能键部分,不使用括号:Instead, write the key parts as nonfunctional key parts, without parentheses:
INDEX (col1, col2)
功能键部分表达式不能引用列前缀。有关解决方法,请参阅本节后面关于
SUBSTRING()和CAST()的讨论。A functional key part expression cannot refer to column prefixes. For a workaround, see the discussion ofSUBSTRING()andCAST()later in this section.在外键规范中不允许使用功能性关键部分。Functional key parts are not permitted in foreign key specifications.
对于 CREATE
TABLE ... LIKE,目标表会保留原始表的功能关键部分。For CREATE
TABLE ... LIKE, the destination table preserves
functional key parts from the original table.
函数索引被实现为隐藏的虚拟生成列,这具有以下影响:Functional indexes are implemented as hidden virtual generated columns, which has these implications:
每个功能键部分都计入表格列总数的限制;请参阅第 10.4.7 节,“表格列数和行大小的限制”。Each functional key part counts against the limit on total number of table columns; see Section 10.4.7, “Limits on Table Column Count and Row Size”.
功能键部分继承适用于生成列的所有限制。示例:Functional key parts inherit all restrictions that apply to generated columns. Examples:
仅允许用于生成列的函数才允许用于功能键部分。Only functions permitted for generated columns are permitted for functional key parts.
不允许使用子查询、参数、变量、存储函数和可加载函数。Subqueries, parameters, variables, stored functions, and loadable functions are not permitted.
有关适用限制的更多信息,请参见 第 15.1.20.8 节,“CREATE TABLE 和生成列”,以及 第 15.1.9.2 节,“ALTER TABLE 和生成列”。For more information about applicable restrictions, see Section 15.1.20.8, “CREATE TABLE and Generated Columns”, and Section 15.1.9.2, “ALTER TABLE and Generated Columns”.
虚拟生成列本身不需要存储。索引本身占用存储空间,就像其他索引一样。The virtual generated column itself requires no storage. The index itself takes up storage space as any other index.
UNIQUE 支持包含函数键部分的索引。然而,主键不能包含函数键部分。主键要求生成列为存储列,但函数键部分是作为虚拟生成列实现的,而不是存储生成列。UNIQUE is supported for indexes that include
functional key parts. However, primary keys cannot include
functional key parts. A primary key requires the generated
column to be stored, but functional key parts are implemented as
virtual generated columns, not stored generated columns.
SPATIAL 和 FULLTEXT 索引不能有函数键部分。SPATIAL and FULLTEXT
indexes cannot have functional key parts.
如果表中没有主键,InnoDB 会自动将第一个 UNIQUE NOT NULL 索引提升为主键。对于具有函数键部分的 UNIQUE NOT
NULL 索引,这是不支持的。If a table contains no primary key, InnoDB
automatically promotes the first UNIQUE NOT
NULL index to the primary key. This is not supported
for UNIQUE NOT NULL indexes that have
functional key parts.
如果存在重复索引,非功能性索引会发出警告。包含功能性关键部分的索引没有此功能。Nonfunctional indexes raise a warning if there are duplicate indexes. Indexes that contain functional key parts do not have this feature.
要删除被功能性关键部分引用的列,必须先删除索引。否则,将发生错误。To remove a column that is referenced by a functional key part, the index must be removed first. Otherwise, an error occurs.
尽管非功能性键部分支持前缀长度的指定,但功能性键部分无法实现此操作。解决方法是使用SUBSTRING()(或本节稍后描述的CAST())。如果要在查询中使用包含SUBSTRING()函数的功能性键部分,则WHERE子句必须包含具有相同参数的SUBSTRING()。在下面的示例中,只有第二个SELECT能够使用该索引,因为这是唯一一个其SUBSTRING()参数与索引规范匹配的查询:Although nonfunctional key parts support a prefix length
specification, this is not possible for functional key parts.
The solution is to use
SUBSTRING() (or
CAST(), as described later in
this section). For a functional key part containing the
SUBSTRING() function to be used
in a query, the WHERE clause must contain
SUBSTRING() with the same
arguments. In the following example, only the second
SELECT is able to use the index
because that is the only query in which the arguments to
SUBSTRING() match the index
specification:
CREATE TABLE tbl ( col1 LONGTEXT, INDEX idx1 ((SUBSTRING(col1, 1, 10))) ); SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 9) = '123456789'; SELECT * FROM tbl WHERE SUBSTRING(col1, 1, 10) = '1234567890';
功能性键部分使得无法用其他方式建立索引的值得以索引,例如JSON值。然而,这必须正确操作才能达到预期效果。例如,以下语法是无效的:Functional key parts enable indexing of values that cannot be
indexed otherwise, such as JSON
values. However, this must be done correctly to achieve the
desired effect. For example, this syntax does not work:
CREATE TABLE employees ( data JSON, INDEX ((data->>'$.name')) );
语法失败,因为:The syntax fails because:
该
->>operator translates intoJSON_UNQUOTE(JSON_EXTRACT(...)).The->>operator translates intoJSON_UNQUOTE(JSON_EXTRACT(...)).JSON_UNQUOTE()返回一个数据类型为LONGTEXT因此隐藏生成的列被分配相同的数据类型。JSON_UNQUOTE()returns a value with a data type ofLONGTEXT, and the hidden generated column thus is assigned the same data type.MySQL 无法索引
LONGTEXT列在关键部分上未加前缀长度,功能性密钥部分不允许前缀长度。MySQL cannot indexLONGTEXTcolumns specified without a prefix length on the key part, and prefix lengths are not permitted in functional key parts.
要索引 JSON 列,你可以尝试使用 CAST() 函数如下:To index the JSON column, you could try using
the CAST() function as follows:
CREATE TABLE employees ( data JSON, INDEX ((CAST(data->>'$.name' AS CHAR(30)))) );
隐藏生成的列被赋予 VARCHAR(30) 数据类型,可以被索引。但这种方法在尝试使用索引时会带来新问题:The hidden generated column is assigned the
VARCHAR(30) data type, which can
be indexed. But this approach produces a new issue when trying
to use the index:
CAST()返回一个字符串,其排序为utf8mb4_0900_ai_ci(服务器默认排序)。CAST()returns a string with the collationutf8mb4_0900_ai_ci(the server default collation).JSON_UNQUOTE()返回一个字符串,其排序为utf8mb4_bin(硬编码)。JSON_UNQUOTE()returns a string with the collationutf8mb4_bin(hard coded).
因此,前述表定义中的索引表达式与以下查询中的WHERE:As a result, there is a collation mismatch between the indexed
expression in the preceding table definition and the
WHERE clause expression in the following
query:
SELECT * FROM employees WHERE data->>'$.name' = 'James';
索引不被使用,因为查询中的表达式和索引表达式不同。为了支持功能性关键部分的此类情景,优化器在寻找索引时会自动剥离CAST()但仅当索引表达式的排序与查询表达式一致时才使用。对于使用带有功能性关键字部分的索引,以下两种解决方案中任一种都可行(尽管它们在效果上有所不同):The index is not used because the expressions in the query and
the index differ. To support this kind of scenario for
functional key parts, the optimizer automatically strips
CAST() when looking for an index
to use, but only if the collation of the
indexed expression matches that of the query expression. For an
index with a functional key part to be used, either of the
following two solutions work (although they differ somewhat in
effect):
存储过程中的语句不允许。当调用例程时,会有一个隐式
JSON_UNQUOTE():Solution 1. Assign the indexed expression the same collation asJSON_UNQUOTE():CREATE TABLE employees ( data JSON, INDEX idx ((CAST(data->>"$.name" AS CHAR(30)) COLLATE utf8mb4_bin)) ); INSERT INTO employees VALUES ('{ "name": "james", "salary": 9000 }'), ('{ "name": "James", "salary": 10000 }'), ('{ "name": "Mary", "salary": 12000 }'), ('{ "name": "Peter", "salary": 8000 }'); SELECT * FROM employees WHERE data->>'$.name' = 'James';->>The->>operator is the same asJSON_UNQUOTE(JSON_EXTRACT(...)), andJSON_UNQUOTE()returns a string with collationutf8mb4_bin. The comparison is thus case-sensitive, and only one row matches:+------------------------------------+ | data | +------------------------------------+ | {"name": "James", "salary": 10000} | +------------------------------------+解决方案 2。 在查询中指定完整表达式:Solution 2. Specify the full expression in the query:
CREATE TABLE employees ( data JSON, INDEX idx ((CAST(data->>"$.name" AS CHAR(30)))) ); INSERT INTO employees VALUES ('{ "name": "james", "salary": 9000 }'), ('{ "name": "James", "salary": 10000 }'), ('{ "name": "Mary", "salary": 12000 }'), ('{ "name": "Peter", "salary": 8000 }'); SELECT * FROM employees WHERE CAST(data->>'$.name' AS CHAR(30)) = 'James';CAST()返回一个字符串,其排序utf8mb4_0900_ai_ci,因此比较大小写不分,两行一致:CAST()returns a string with collationutf8mb4_0900_ai_ci, so the comparison case-insensitive and two rows match:+------------------------------------+ | data | +------------------------------------+ | {"name": "james", "salary": 9000} | | {"name": "James", "salary": 10000} | +------------------------------------+
请注意,虽然优化器支持自动剥离 CAST() 并带有索引生成的列,但以下方法无效,因为它会产生不同的结果(Bug#27337092):Be aware that although the optimizer supports automatically
stripping CAST() with indexed
generated columns, the following approach does not work because
it produces a different result with and without an index
(Bug#27337092):
mysql>CREATE TABLE employees (data JSON,generated_col VARCHAR(30) AS (CAST(data->>'$.name' AS CHAR(30))));Query OK, 0 rows affected, 1 warning (0.03 sec) mysql>INSERT INTO employees (data)VALUES ('{"name": "james"}'), ('{"name": "James"}');Query OK, 2 rows affected, 1 warning (0.01 sec) Records: 2 Duplicates: 0 Warnings: 1 mysql>SELECT * FROM employees WHERE data->>'$.name' = 'James';+-------------------+---------------+ | data | generated_col | +-------------------+---------------+ | {"name": "James"} | James | +-------------------+---------------+ 1 row in set (0.00 sec) mysql>ALTER TABLE employees ADD INDEX idx (generated_col);Query OK, 0 rows affected, 1 warning (0.03 sec) Records: 0 Duplicates: 0 Warnings: 1 mysql>SELECT * FROM employees WHERE data->>'$.name' = 'James';+-------------------+---------------+ | data | generated_col | +-------------------+---------------+ | {"name": "james"} | james | | {"name": "James"} | James | +-------------------+---------------+ 2 rows in set (0.01 sec)
索引 UNIQUE 索引创建了一个约束,使得索引中的所有值必须不同。如果你尝试添加一个键值与现有行匹配的新行,会发生错误。如果你在 UNIQUE,列值必须在前缀长度内唯一。UNIQUE 索引允许多个 NULL 值,且列可以包含 NULLA 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.
如果一个表的 PRIMARY KEY UNIQUE NOT NULL 索引,且仅由一个整数类型的列组成,你可以使用 _rowid 来指代索引列 SELECT 语句,具体如下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:
:
_rowid指PRIMARY KEY(如果存在一个由单一整数列组成的PRIMARY KEY列。如果存在PRIMARY KEY但不包含单一整数列,则_rowid无法使用。_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.否则,
_rowid指第一个UNIQUE NOT NULL索引,如果该索引仅包含一个整数列。如果第一个UNIQUE NOT NULL索引不包含单个整数列,则_rowid无法使用。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索引仅支持 InnoDB 和 MyISAM 表,且仅包含CHAR, VARCHAR, TEXT 列。索引总是覆盖整个列;不支持列前缀索引,且如果指定,任何前缀长度都将被忽略。详见 第 14.9 节,“全文搜索函数”。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 14.9, “Full-Text Search Functions”, for details of operation.
InnoDB 支持多值索引。多值索引是定义在存储数组数组的列上的次级索引。“normal”索引为每个数据记录(1:1)有一个索引记录。多值索引可以为单个数据记录(N:1)设置多个索引记录。多值索引旨在索引 JSON 数组。例如,在下一个 JSON 文档中,定义在邮政编码数组上的多值索引为每个邮政编码创建一个索引记录,每个索引记录引用的是相同的数据记录。InnoDB supports multi-valued indexes. A
multi-valued index is a secondary index defined on a column that
stores an array of values. A “normal” index has one
index record for each data record (1:1). A multi-valued index
can have multiple index records for a single data record (N:1).
Multi-valued indexes are intended for indexing
JSON arrays. For example, a multi-valued
index defined on the array of zip codes in the following JSON
document creates an index record for each zip code, with each
index record referencing the same data record.
{
"user":"Bob",
"user_id":31,
"zipcode":[94477,94536]
}
创建多值索引Creating multi-valued Indexes
你可以在 CREATE TABLE, ALTER TABLE,或者 CREATE INDEX句。这需要在索引定义中使用CAST(... AS ...
ARRAY)在索引定义中,将 JSON SQL 数据类型数组。然后透明地生成一个虚拟列,包含 SQL 数据类型数组中的值;最后,在虚拟列上创建函数索引(也称为虚拟索引)。它是定义在 SQL 数据类型数组中虚拟列值上的函数索引,构成多值索引。You can create a multi-valued index in a
CREATE TABLE,
ALTER TABLE, or
CREATE INDEX statement. This
requires using CAST(... AS ...
ARRAY) in the index definition, which casts same-typed
scalar values in a JSON array to an SQL data
type array. A virtual column is then generated transparently
with the values in the SQL data type array; finally, a
functional index (also referred to as a virtual index) is
created on the virtual column. It is the functional index
defined on the virtual column of values from the SQL data type
array that forms the multi-valued index.
The examples in the following list show the three different ways
in which a multi-valued index zips can be
created on an array $.zipcode on a
JSON影响最近语句生成的第一个值custinfo in a
table named customers. In each case, the JSON
array is cast to an SQL data type array of
UNSIGNED整数值。The examples in the following list show the three different ways
in which a multi-valued index zips can be
created on an array $.zipcode on a
JSON column custinfo in a
table named customers. In each case, the JSON
array is cast to an SQL data type array of
UNSIGNED integer values.
CREATE TABLE:CREATE TABLEonly:CREATE TABLE customers ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, custinfo JSON, INDEX zips( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) ) );CREATE TABLE加ALTER TABLE:CREATE TABLEplusALTER TABLE:CREATE TABLE customers ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, custinfo JSON ); ALTER TABLE customers ADD INDEX zips( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );CREATE TABLE加CREATE INDEX:CREATE TABLEplusCREATE INDEX:CREATE TABLE customers ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, custinfo JSON ); CREATE INDEX zips ON customers ( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );
多值索引也可以定义为复合索引的一部分。本示例展示了一个复合索引,其中包含两个单值部分(用于 id 和 modified columns),以及一个多值部分(用于 custinfo 列):A multi-valued index can also be defined as part of a composite
index. This example shows a composite index that includes two
single-valued parts (for the id and
modified columns), and one multi-valued part
(for the custinfo column):
CREATE TABLE customers (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
custinfo JSON
);
ALTER TABLE customers ADD INDEX comp(id, modified,
(CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );
复合索引中只能使用一个多值关键部分。多值密钥部分可以相对于密钥的其他部分以任意顺序使用。换句话说,刚才展示的 ALTER
TABLEOnly one multi-valued key part can be used in a composite index.
The multi-valued key part may be used in any order relative to
the other parts of the key. In other words, the ALTER
TABLE statement just shown could have used
comp(id, (CAST(custinfo->'$.zipcode' AS UNSIGNED
ARRAY), modified)) (or any other ordering) and still
have been valid.
使用多值索引Using multi-valued Indexes
优化器在以下函数指定为 WHERE:The optimizer uses a multi-valued index to fetch records when
the following functions are specified in a
WHERE clause:
我们可以通过创建并填充 customers使用 CREATE TABLE 和 INSERT 语句来演示:We can demonstrate this by creating and populating the
customers table using the following
CREATE TABLE and INSERT
statements:
mysql>CREATE TABLE customers (->id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,->modified DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,->custinfo JSON->);Query OK, 0 rows affected (0.51 sec) mysql>INSERT INTO customers VALUES->(NULL, NOW(), '{"user":"Jack","user_id":37,"zipcode":[94582,94536]}'),->(NULL, NOW(), '{"user":"Jill","user_id":22,"zipcode":[94568,94507,94582]}'),->(NULL, NOW(), '{"user":"Bob","user_id":31,"zipcode":[94477,94507]}'),->(NULL, NOW(), '{"user":"Mary","user_id":72,"zipcode":[94536]}'),->(NULL, NOW(), '{"user":"Ted","user_id":56,"zipcode":[94507,94582]}');Query OK, 5 rows affected (0.07 sec) Records: 5 Duplicates: 0 Warnings: 0
首先,我们在 customers 表上执行三个查询,分别使用 MEMBER OF()、JSON_CONTAINS() 和 JSON_OVERLAPS(),每个查询的结果如下所示:First we execute three queries on the
customers table, one each using
MEMBER OF(),
JSON_CONTAINS(), and
JSON_OVERLAPS(), with the result from each
query shown here:
mysql>SELECT * FROM customers->WHERE 94507 MEMBER OF(custinfo->'$.zipcode');+----+---------------------+-------------------------------------------------------------------+ | id | modified | custinfo | +----+---------------------+-------------------------------------------------------------------+ | 2 | 2019-06-29 22:23:12 | {"user": "Jill", "user_id": 22, "zipcode": [94568, 94507, 94582]} | | 3 | 2019-06-29 22:23:12 | {"user": "Bob", "user_id": 31, "zipcode": [94477, 94507]} | | 5 | 2019-06-29 22:23:12 | {"user": "Ted", "user_id": 56, "zipcode": [94507, 94582]} | +----+---------------------+-------------------------------------------------------------------+ 3 rows in set (0.00 sec) mysql>SELECT * FROM customers->WHERE JSON_CONTAINS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+---------------------+-------------------------------------------------------------------+ | id | modified | custinfo | +----+---------------------+-------------------------------------------------------------------+ | 2 | 2019-06-29 22:23:12 | {"user": "Jill", "user_id": 22, "zipcode": [94568, 94507, 94582]} | | 5 | 2019-06-29 22:23:12 | {"user": "Ted", "user_id": 56, "zipcode": [94507, 94582]} | +----+---------------------+-------------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql>SELECT * FROM customers->WHERE JSON_OVERLAPS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+---------------------+-------------------------------------------------------------------+ | id | modified | custinfo | +----+---------------------+-------------------------------------------------------------------+ | 1 | 2019-06-29 22:23:12 | {"user": "Jack", "user_id": 37, "zipcode": [94582, 94536]} | | 2 | 2019-06-29 22:23:12 | {"user": "Jill", "user_id": 22, "zipcode": [94568, 94507, 94582]} | | 3 | 2019-06-29 22:23:12 | {"user": "Bob", "user_id": 31, "zipcode": [94477, 94507]} | | 5 | 2019-06-29 22:23:12 | {"user": "Ted", "user_id": 56, "zipcode": [94507, 94582]} | +----+---------------------+-------------------------------------------------------------------+ 4 rows in set (0.00 sec)
接下来,我们对前面三条查询分别运行 EXPLAIN:Next, we run EXPLAIN on each of
the previous three queries:
mysql>EXPLAIN SELECT * FROM customers->WHERE 94507 MEMBER OF(custinfo->'$.zipcode');+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql>EXPLAIN SELECT * FROM customers->WHERE JSON_CONTAINS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql>EXPLAIN SELECT * FROM customers->WHERE JSON_OVERLAPS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | ALL | NULL | NULL | NULL | NULL | 5 | 100.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.01 sec)
刚才显示的三条查询都无法使用任何索引。为了解决这个问题,我们可以在 JSON 列(custinfo)中的 zipcode 数组上添加一个多值索引,如下所示:None of the three queries just shown are able to use any keys.
To solve this problem, we can add a multi-valued index on the
zipcode array in the JSON
column (custinfo), like this:
mysql>ALTER TABLE customers->ADD INDEX zips( (CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)) );Query OK, 0 rows affected (0.47 sec) Records: 0 Duplicates: 0 Warnings: 0
当我们再次运行之前的 EXPLAIN 语句时,现在可以观察到查询可以(并且确实)使用刚刚创建的索引 zips:When we run the previous EXPLAIN statements
again, we can now observe that the queries can (and do) use the
index zips that was just created:
mysql>EXPLAIN SELECT * FROM customers->WHERE 94507 MEMBER OF(custinfo->'$.zipcode');+----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | ref | zips | zips | 9 | const | 1 | 100.00 | Using where | +----+-------------+-----------+------------+------+---------------+------+---------+-------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql>EXPLAIN SELECT * FROM customers->WHERE JSON_CONTAINS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | range | zips | zips | 9 | NULL | 6 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql>EXPLAIN SELECT * FROM customers->WHERE JSON_OVERLAPS(custinfo->'$.zipcode', CAST('[94507,94582]' AS JSON));+----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ | 1 | SIMPLE | customers | NULL | range | zips | zips | 9 | NULL | 6 | 100.00 | Using where | +----+-------------+-----------+------------+-------+---------------+------+---------+------+------+----------+-------------+ 1 row in set, 1 warning (0.01 sec)
多值索引可以被定义为唯一键。如果定义为唯一键,尝试插入已存在于多值索引中的值会返回重复键错误。如果重复值已经存在,尝试添加唯一多值索引会失败,如下所示:A multi-valued index can be defined as a unique key. If defined as a unique key, attempting to insert a value already present in the multi-valued index returns a duplicate key error. If duplicate values are already present, attempting to add a unique multi-valued index fails, as shown here:
mysql>ALTER TABLE customers DROP INDEX zips;Query OK, 0 rows affected (0.55 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql>ALTER TABLE customers->ADD UNIQUE INDEX zips((CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)));ERROR 1062 (23000): Duplicate entry '[94507, ' for key 'customers.zips' mysql>ALTER TABLE customers->ADD INDEX zips((CAST(custinfo->'$.zipcode' AS UNSIGNED ARRAY)));Query OK, 0 rows affected (0.36 sec) Records: 0 Duplicates: 0 Warnings: 0
多值索引的特性Characteristics of Multi-Valued Indexes
多值索引具有以下附加特征:Multi-valued indexes have the additional characteristics listed here:
影响多值索引的 DML 操作处理方式与影响普通索引的 DML 操作相同,唯一的区别是单个聚簇索引记录可能会有多次插入或更新。DML operations that affect multi-valued indexes are handled in the same way as DML operations that affect a normal index, with the only difference being that there may be more than one insert or update for a single clustered index record.
可空性与多值索引:Nullability and multi-valued indexes:
如果多值键部分为空数组,则不会向索引中添加任何条目,并且数据记录不能通过索引扫描访问。If a multi-valued key part has an empty array, no entries are added to the index, and the data record is not accessible by an index scan.
如果多值键部分生成返回
NULL值,则在多值索引中添加包含NULL的单个条目。如果键部分定义为NOT NULL,则会报告错误。If multi-valued key part generation returns aNULLvalue, a single entry containingNULLis added to the multi-valued index. If the key part is defined asNOT NULL, an error is reported.如果类型化数组列设置为
NULL,存储引擎将存储一个包含NULL且指向数据记录的单条记录。If the typed array column is set toNULL, the storage engine stores a single record containingNULLthat points to the data record.索引数组中不允许
JSON空值。如果返回的任何值为NULL,则将其视为 JSON 空值并报告 无效 JSON 值 错误。JSONnull values are not permitted in indexed arrays. If any returned value isNULL, it is treated as a JSON null and an Invalid JSON value error is reported.
由于多值索引是虚拟列上的虚拟索引,它们必须遵守与虚拟生成列上的二级索引相同的规则。Because multi-valued indexes are virtual indexes on virtual columns, they must adhere to the same rules as secondary indexes on virtual generated columns.
空数组不会添加索引记录。Index records are not added for empty arrays.
多值索引的限制与约束Limitations and Restrictions on Multi-valued Indexes
多值索引受到此处列出的限制和约束的影响:Multi-valued indexes are subject to the limitations and restrictions listed here:
每个多值索引仅允许一个多值键部分。然而,
CAST(... AS ... ARRAY)表达式可以在JSON文档中引用多个数组,如下所示:Only one multi-valued key part is permitted per multi-valued index. However, theCAST(... AS ... ARRAY)expression can refer to multiple arrays within aJSONdocument, as shown here:CAST(data->'$.arr[*][*]' AS UNSIGNED ARRAY)
在这种情况下,所有匹配 JSON 表达式的值都作为一个单一的扁平数组存储在索引中。In this case, all values matching the JSON expression are stored in the index as a single flat array.
具有多值键部分的索引不支持排序,因此不能用作主键。出于同样的原因,多值索引不能使用
ASC或DESC关键字定义。An index with a multi-valued key part does not support ordering and therefore cannot be used as a primary key. For the same reason, a multi-valued index cannot be defined using theASCorDESCkeyword.多值索引不能是覆盖索引。A multi-valued index cannot be a covering index.
多值索引每条记录的最大值数量由可存储在单个撤销日志页上的数据量决定,即 65221 字节(64K 减去 315 字节的开销),这意味着键值的最大总长度也为 65221 字节。最大键数取决于多种因素,因此无法定义具体的限制。测试显示,多值索引每条记录最多可允许 1604 个整数键,例如。当达到限制时,会报告如下类似错误:错误 3905 (HY000):超出多值索引 'idx' 每条记录的最大值数量 1 个值。The maximum number of values per record for a multi-valued index is determined by the amount of data than can be stored on a single undo log page, which is 65221 bytes (64K minus 315 bytes for overhead), which means that the maximum total length of key values is also 65221 bytes. The maximum number of keys depends on various factors, which prevents defining a specific limit. Tests have shown a multi-valued index to permit as many as 1604 integer keys per record, for example. When the limit is reached, an error similar to the following is reported: ERROR 3905 (HY000): Exceeded max number of values per record for multi-valued index 'idx' by 1 value(s).
在多值键部分中唯一允许的表达式类型是
JSON表达式。表达式不必引用插入到被索引列中的 JSON 文档中的现有元素,但自身必须是语法上有效的。The only type of expression that is permitted in a multi-valued key part is aJSONexpression. The expression need not reference an existing element in a JSON document inserted into the indexed column, but must itself be syntactically valid.由于相同的聚簇索引记录的索引记录分散在多值索引中,多值索引不支持范围扫描或仅索引扫描。Because index records for the same clustered index record are dispersed throughout a multi-valued index, a multi-valued index does not support range scans or index-only scans.
多值索引不允许在外键规范中使用。Multi-valued indexes are not permitted in foreign key specifications.
不能为多值索引定义索引前缀。Index prefixes cannot be defined for multi-valued indexes.
不能在转换为
BINARY的数据上定义多值索引(请参阅CAST()函数的说明)。Multi-valued indexes cannot be defined on data cast asBINARY(see the description of theCAST()function).不支持在线创建多值索引,这意味着操作使用
ALGORITHM=COPY。参见 性能和空间要求。Online creation of a multi-value index is not supported, which means the operation usesALGORITHM=COPY. See Performance and Space Requirements.除了以下两种字符集和排序规则的组合之外,不支持多值索引的其他字符集和排序规则:Character sets and collations other than the following two combinations of character set and collation are not supported for multi-valued indexes:
默认
binary排序规则的binary字符集Thebinarycharacter set with the defaultbinarycollation默认
utf8mb4_0900_as_cs排序规则的utf8mb4字符集。Theutf8mb4character set with the defaultutf8mb4_0900_as_cscollation.
与
InnoDB表的其他列索引相同,无法使用USING HASH创建多值索引;尝试这样做会产生警告:此存储引擎不支持 HASH 索引算法,而是使用存储引擎默认值。(USING BTREE) 如常规支持。As with other indexes on columns ofInnoDBtables, a multi-valued index cannot be created withUSING HASH; attempting to do so results in a warning: This storage engine does not support the HASH index algorithm, storage engine default was used instead. (USING BTREEis supported as usual.)
MyISAM、InnoDB、NDB 和 ARCHIVE 存储引擎支持空间列,例如 POINT 和 GEOMETRY。(第 13.4 节,“空间数据类型” 描述了空间数据类型)。然而,不同引擎对空间列的索引支持程度不同。空间列上的空间索引和非空间索引根据以下规则提供。The MyISAM,
InnoDB,
NDB, and
ARCHIVE storage engines support
spatial columns such as POINT and
GEOMETRY.
(Section 13.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 have these characteristics:
仅适用于
InnoDB和MyISAM表。在其他存储引擎上指定SPATIAL INDEX会导致错误。Available only forInnoDBandMyISAMtables. SpecifyingSPATIAL INDEXfor other storage engines results in an error.在空间列上创建索引 必须 是
SPATIAL索引。因此,为空间列创建索引时,SPATIAL关键字是可选的,但隐式存在。An index on a spatial column must be aSPATIALindex. TheSPATIALkeyword is thus optional but implicit for creating an index on a spatial column.仅适用于单个空间列。无法在多个空间列上创建空间索引。Available for single spatial columns only. A spatial index cannot be created over multiple spatial columns.
索引列必须为
NOT NULL。Indexed columns must beNOT NULL.禁止列前缀长度。索引的是每列的完整宽度。Column prefix lengths are prohibited. The full width of each column is indexed.
不允许用于主键或唯一索引。Not permitted for a primary key or unique index.
空间列上的非空间索引(使用 INDEX、UNIQUE 或 PRIMARY KEY 创建)具有以下特性:Nonspatial indexes on spatial columns (created with
INDEX, UNIQUE, or
PRIMARY KEY) have these characteristics:
允许用于支持空间列的任意存储引擎,但不包括
ARCHIVE。Permitted for any storage engine that supports spatial columns exceptARCHIVE.除非索引是主键,否则列可以为
NULL。Columns can beNULLunless the index is a primary key.非
SPATIAL索引的索引类型取决于存储引擎。目前使用 B 树。The index type for a non-SPATIALindex depends on the storage engine. Currently, B-tree is used.仅对可以包含
NULL值的列允许使用InnoDB、MyISAM和MEMORY表。Permitted for a column that can haveNULLvalues only forInnoDB,MyISAM, andMEMORYtables.
在键部分列表之后,可以指定索引选项。index_option 的值可以是以下任意选项:Following the key part list, index options can be given. An
index_option value can be any of the
following:
KEY_BLOCK_SIZE [=]value对于
MyISAM表,KEY_BLOCK_SIZE可选地指定用于索引键块的字节大小。该值被视为提示;如有必要,可以使用不同的大小。为单个索引定义指定的KEY_BLOCK_SIZE值会覆盖表级的KEY_BLOCK_SIZE值。ForMyISAMtables,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_SIZE不支持InnoDB表的索引级别。请参阅 第 15.1.20 节,“CREATE TABLE 语句”。KEY_BLOCK_SIZEis not supported at the index level forInnoDBtables. See Section 15.1.20, “CREATE TABLE Statement”.index_type某些存储引擎允许您在创建索引时指定索引类型。例如:Some 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;
表 15.1,“存储引擎的索引类型” 显示了不同存储引擎支持的允许索引类型值。如果列出了多个索引类型,则在未给出索引类型说明符时,第一个是默认值。表中未列出的存储引擎在索引定义中不支持
index_type子句。Table 15.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 anindex_typeclause in index definitions.该
index_type子句不能用于FULLTEXT INDEX规格。全文索引的实现依赖于存储引擎。空间索引实现为 R 树索引。Theindex_typeclause cannot be used forFULLTEXT INDEXspecifications. Full-text index implementation is storage-engine dependent. Spatial indexes are implemented as R-tree indexes.如果你指定了一个索引类型,但该类型不适用于某个存储引擎,但有其他索引类型可供引擎使用且不影响查询结果,则使用该类型。解析器识别
RTREE作为类型名。这仅允许用于SPATIAL索引。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 recognizesRTREEas a type name. This is permitted only forSPATIALindexes.BTREE索引通过NDB存储引擎作为 T 树索引实现。BTREEindexes are implemented by theNDBstorage engine as T-tree indexes.Note对于
NDB表列的索引,USING选项只能为唯一索引或主键指定。USING HASH阻止创建有序索引;否则,在NDB表会自动生成有序索引和哈希索引,每个索引索引相同的列集。For indexes onNDBtable 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.对于包含一个或多个
NULL列的唯一索引,NDB表,哈希索引只能用于查找文字值,这意味着IS [NOT] NULL条件需要对表进行全面扫描。一种变通方法是确保使用一个或多个NULL列的唯一索引,始终包含有序索引;也就是说,创建索引时避免使用USING HASH。For unique indexes that include one or moreNULLcolumns 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.如果你指定了一个索引类型,但该类型不适用于某个存储引擎,但有其他索引类型可供引擎使用且不影响查询结果,则引擎使用该类型。解析器识别
RTREE作为类型名,但目前无法为任何存储引擎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 recognizesRTREEas a type name, but currently this cannot be specified for any storage engine.Note在
index_type子句之前使用该ON选项已被弃用;预计在未来的 MySQL 版本中将移除在此位置使用该选项的支持。如果同一个tbl_nameindex_type选项同时在前后位置给出,则最终应用后者。Use of theindex_typeoption before theONclause is deprecated; 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.TYPE被认为是type_nameUSING type_name的同义词。但是,USING是首选形式。TYPEis recognized as a synonym fortype_nameUSING. However,type_nameUSINGis the preferred form.下表显示了支持
index_type选项的存储引擎的索引特性。The following tables show index characteristics for the storage engines that support theindex_typeoption.表 15.2 InnoDB 存储引擎索引特性Table 15.2 InnoDB Storage Engine Index Characteristics
索引类Index Class 索引类型Index Type 存储 NULL 值Stores NULL VALUES 允许多个 NULL 值Permits Multiple NULL Values IS NULL 扫描类型IS NULL Scan Type IS NOT NULL 扫描类型IS NOT NULL Scan Type 主键Primary key BTREEBTREE否No 否No 不适用N/A 不适用N/A 唯一Unique BTREEBTREE是Yes 是Yes 索引Index 索引Index 键Key BTREEBTREE是Yes 是Yes 索引Index 索引Index FULLTEXTFULLTEXT不适用N/A 是Yes 是Yes 表Table 表Table SPATIALSPATIAL不适用N/A 否No 否No 不适用N/A 不适用N/A 表 15.3 MyISAM 存储引擎索引特性Table 15.3 MyISAM Storage Engine Index Characteristics
索引类Index Class 索引类型Index Type 存储 NULL 值Stores NULL VALUES 允许多个 NULL 值Permits Multiple NULL Values IS NULL 扫描类型IS NULL Scan Type IS NOT NULL 扫描类型IS NOT NULL Scan Type 主键Primary key BTREEBTREE否No 否No 不适用N/A 不适用N/A 唯一Unique BTREEBTREE是Yes 是Yes 索引Index 索引Index 键Key BTREEBTREE是Yes 是Yes 索引Index 索引Index FULLTEXTFULLTEXT不适用N/A 是Yes 是Yes 表Table 表Table SPATIALSPATIAL不适用N/A 否No 否No 不适用N/A 不适用N/A 表 15.4 MEMORY 存储引擎索引特性Table 15.4 MEMORY Storage Engine Index Characteristics
索引类Index Class 索引类型Index Type 存储 NULL 值Stores NULL VALUES 允许多个 NULL 值Permits Multiple NULL Values IS NULL 扫描类型IS NULL Scan Type IS NOT NULL 扫描类型IS NOT NULL Scan Type 主键Primary key BTREEBTREE否No 否No 不适用N/A 不适用N/A 唯一Unique BTREEBTREE是Yes 是Yes 索引Index 索引Index 键Key BTREEBTREE是Yes 是Yes 索引Index 索引Index 主键Primary key HASHHASH否No 否No 不适用N/A 不适用N/A 唯一Unique HASHHASH是Yes 是Yes 索引Index 索引Index 键Key HASHHASH是Yes 是Yes 索引Index 索引Index 表 15.5 NDB 存储引擎索引特性Table 15.5 NDB Storage Engine Index Characteristics
索引类Index Class 索引类型Index Type 存储 NULL 值Stores NULL VALUES 允许多个 NULL 值Permits Multiple NULL Values IS NULL 扫描类型IS NULL Scan Type IS NOT NULL 扫描类型IS NOT NULL Scan Type 主键Primary key BTREEBTREE否No 否No 索引Index 索引Index 唯一Unique BTREEBTREE是Yes 是Yes 索引Index 索引Index 键Key BTREEBTREE是Yes 是Yes 索引Index 索引Index 主键Primary key HASHHASH否No 否No 表格(见注 1)Table (see note 1) 表格(见注 1)Table (see note 1) 唯一Unique HASHHASH是Yes 是Yes 表格(见注 1)Table (see note 1) 表格(见注 1)Table (see note 1) 键Key HASHHASH是Yes 是Yes 表格(见注 1)Table (see note 1) 表格(见注 1)Table (see note 1) 表格注:Table note:
1.
USING HASH防止创建隐式有序索引。1.USING HASHprevents creation of an implicit ordered index.WITH PARSERparser_name此选项只能用于
FULLTEXT索引。如果全文索引和搜索操作需要特殊处理,它会将解析器插件与索引关联。InnoDB和MyISAM支持全文解析器插件。如果你有一个带有关联全文解析器插件的MyISAM表,可以使用ALTER TABLE将表转换为InnoDB。更多信息请参见 全文解析器插件 和 编写全文解析器插件。This option can be used only withFULLTEXTindexes. 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'索引定义可以包含最多 1024 个字符的可选注释。Index definitions can include an optional comment of up to 1024 characters.
索引页的
MERGE_THRESHOLD可以通过CREATE INDEX语句中的index_optionCOMMENT子句为各个索引进行配置。例如:TheMERGE_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';
如果在删除一行或通过更新操作缩短行时,索引页的页满百分比低于
MERGE_THRESHOLD值,InnoDB会尝试将索引页与相邻的索引页合并。默认的MERGE_THRESHOLD值为 50,这是之前硬编码的值。If the page-full percentage for an index page falls below theMERGE_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_THRESHOLD也可以使用CREATE TABLE和ALTER TABLE语句在索引级别和表级别定义。更多信息,请参见 第 17.8.11 节,“配置索引页的合并阈值”。MERGE_THRESHOLDcan also be defined at the index level and table level usingCREATE TABLEandALTER TABLEstatements. For more information, see Section 17.8.11, “Configuring the Merge Threshold for Index Pages”.VISIBLE,INVISIBLEVISIBLE,INVISIBLE指定索引的可见性。索引默认是可见的。不可见索引不会被优化器使用。索引可见性的指定适用于主键以外的索引(无论显式还是隐式)。更多信息,请参见 第 10.3.12 节,“不可见索引”。Specify index visibility. Indexes are visible by default. An invisible index is not used by the optimizer. Specification of index visibility applies to indexes other than primary keys (either explicit or implicit). For more information, see Section 10.3.12, “Invisible Indexes”.
ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE用于为主存储引擎和辅助存储引擎指定索引属性。这些选项为将来使用而保留。TheENGINE_ATTRIBUTEandSECONDARY_ENGINE_ATTRIBUTEare used to specify index attributes for primary and secondary storage engines. The options are reserved for future use.分配给此选项的值是包含有效 JSON 文档的字符串字面量或空字符串('')。无效的 JSON 会被拒绝。The value assigned to this option is a string literal containing a valid JSON document or an empty string (''). Invalid JSON is rejected.
CREATE INDEX i1 ON t1 (c1) ENGINE_ATTRIBUTE='{"key":"value"}';ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE的值可以重复而不会出错。在这种情况下,将使用最后指定的值。ENGINE_ATTRIBUTEandSECONDARY_ENGINE_ATTRIBUTEvalues can be repeated without error. In this case, the last specified value is used.ENGINE_ATTRIBUTE和SECONDARY_ENGINE_ATTRIBUTE的值不会被服务器检查,也不会在更改表的存储引擎时清除。ENGINE_ATTRIBUTEandSECONDARY_ENGINE_ATTRIBUTEvalues are not checked by the server, nor are they cleared when the table's storage engine is changed.
ALGORITHM 和 LOCK 子句可用于影响表复制方法以及在修改其索引时对表进行读写的并发级别。它们的含义与 ALTER TABLE 语句相同。更多信息,请参见 第 15.1.9 节,“ALTER TABLE 语句”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 15.1.9, “ALTER TABLE Statement”
NDB Cluster 支持使用与标准 MySQL Server 相同的 ALGORITHM=INPLACE 语法执行在线操作。更多信息,请参见 第 25.6.12 节,“在 NDB Cluster 中使用 ALTER TABLE 的在线操作”。NDB Cluster supports online operations using the same
ALGORITHM=INPLACE syntax used with the
standard MySQL Server. See
Section 25.6.12, “Online Operations with ALTER TABLE in NDB Cluster”, for more
information.