InnoDB
supports secondary indexes on virtual generated columns. InnoDB
支持虚拟生成列上的辅助索引。Other index types are not supported. A secondary index defined on a virtual column is sometimes referred to as a “virtual index”.不支持其他索引类型。在虚拟列上定义的辅助索引有时称为“虚拟索引”。
A secondary index may be created on one or more virtual columns or on a combination of virtual columns and regular columns or stored generated columns. 可以在一个或多个虚拟列、虚拟列和常规列的组合或存储的生成列上创建辅助索引。Secondary indexes that include virtual columns may be defined as 包含虚拟列的二级索引可以定义为唯一索引。UNIQUE
.
When a secondary index is created on a virtual generated column, generated column values are materialized in the records of the index. 在虚拟生成的列上创建辅助索引时,生成的列值将在索引的记录中具体化。If the index is a covering index (one that includes all the columns retrieved by a query), generated column values are retrieved from materialized values in the index structure instead of computed “on the fly”.如果索引是覆盖索引(包括查询检索到的所有列),则从索引结构中的物化值检索生成的列值,而不是“动态”计算的值。
There are additional write costs to consider when using a secondary index on a virtual column due to computation performed when materializing virtual column values in secondary index records during 当在INSERT
and UPDATE
operations. INSERT
和UPDATE
操作期间实现二次索引记录中的虚拟列值时进行计算时,在虚拟列上使用辅助索引时需要考虑额外的写入成本。Even with additional write costs, secondary indexes on virtual columns may be preferable to generated stored columns, which are materialized in the clustered index, resulting in larger tables that require more disk space and memory. 即使有额外的写入成本,虚拟列上的二级索引也可能比生成的存储列更好,这些存储列在聚集索引中具体化,从而生成需要更多磁盘空间和内存的更大的表。If a secondary index is not defined on a virtual column, there are additional costs for reads, as virtual column values must be computed each time the column's row is examined.如果未在虚拟列上定义辅助索引,则会增加读取成本,因为每次检查列的行时都必须计算虚拟列值。
Values of an indexed virtual column are MVCC-logged to avoid unnecessary recomputation of generated column values during rollback or during a purge operation. 索引虚拟列的值将被MVCC记录,以避免在回滚或清除操作期间对生成的列值进行不必要的重新计算。The data length of logged values is limited by the index key limit of 767 bytes for 对于COMPACT
and REDUNDANT
row formats, and 3072 bytes for DYNAMIC
and COMPRESSED
row formats.COMPACT
(紧凑)和REDUNDANT
(冗余)行格式,记录值的数据长度受索引键限制767字节,对于动态和压缩行格式,受索引键限制3072字节。
Adding or dropping a secondary index on a virtual column is an in-place operation.在虚拟列上添加或删除辅助索引是一项就地操作。
As noted elsewhere, 正如其他地方所指出的,JSON
columns cannot be indexed directly. JSON
列不能直接索引。To create an index that references such a column indirectly, you can define a generated column that extracts the information that should be indexed, then create an index on the generated column, as shown in this example:要创建间接引用此类列的索引,可以定义一个生成的列,该列提取应编制索引的信息,然后在生成的列上创建索引,如本例所示:
mysql>CREATE TABLE jemp (
->c JSON,
->g INT GENERATED ALWAYS AS (c->"$.id"),
->INDEX i (g)
->);
Query OK, 0 rows affected (0.28 sec) mysql>INSERT INTO jemp (c) VALUES
>('{"id": "1", "name": "Fred"}'), ('{"id": "2", "name": "Wilma"}'),
>('{"id": "3", "name": "Barney"}'), ('{"id": "4", "name": "Betty"}');
Query OK, 4 rows affected (0.04 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql>SELECT c->>"$.name" AS name
>FROM jemp WHERE g > 2;
+--------+ | name | +--------+ | Barney | | Betty | +--------+ 2 rows in set (0.00 sec) mysql>EXPLAIN SELECT c->>"$.name" AS name
>FROM jemp WHERE g > 2\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: jemp partitions: NULL type: range possible_keys: i key: i key_len: 5 ref: NULL rows: 2 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select json_unquote(json_extract(`test`.`jemp`.`c`,'$.name')) AS `name` from `test`.`jemp` where (`test`.`jemp`.`g` > 2) 1 row in set (0.00 sec)
(We have wrapped the output from the last statement in this example to fit the viewing area.)(我们已经包装了本例中最后一条语句的输出,以适合查看区域。)
When you use 对EXPLAIN
on a SELECT
or other SQL statement containing one or more expressions that use the ->
or ->>
operator, these expressions are translated into their equivalents using JSON_EXTRACT()
and (if needed) JSON_UNQUOTE()
instead, as shown here in the output from SHOW WARNINGS
immediately following this EXPLAIN
statement:SELECT
或包含一个或多个使用->
运算符或->>
运算符的表达式的其他SQL语句使用EXPLAIN
时,这些表达式将使用JSON_EXTRACT()
和(如果需要)JSON_UNQUOTE()
转换为等效表达式,如下面EXPLAIN
语句后面的SHOW WARNINGS
输出所示:
mysql>EXPLAIN SELECT c->>"$.name"
>FROM jemp WHERE g > 2 ORDER BY c->"$.name"\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: jemp partitions: NULL type: range possible_keys: i key: i key_len: 5 ref: NULL rows: 2 filtered: 100.00 Extra: Using where; Using filesort 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select json_unquote(json_extract(`test`.`jemp`.`c`,'$.name')) AS `c->>"$.name"` from `test`.`jemp` where (`test`.`jemp`.`g` > 2) order by json_extract(`test`.`jemp`.`c`,'$.name') 1 row in set (0.00 sec)
See the descriptions of the 请参阅->
and ->>
operators, as well as those of the JSON_EXTRACT()
and JSON_UNQUOTE()
functions, for additional information and examples.->
和->>
运算符的说明,以及JSON_EXTRACT()
和JSON_UNQUOTE()
函数的说明,以获取更多信息和示例。
This technique also can be used to provide indexes that indirectly reference columns of other types that cannot be indexed directly, such as 此技术还可用于提供间接引用无法直接索引的其他类型的列(如GEOMETRY
columns.GEOMETRY
列)的索引。
In MySQL 8.0.21 and later, it is also possible to create an index on a 在MySQL 8.0.21及更高版本中,还可以使用JSON
column using the JSON_VALUE()
function with an expression that can be used to optimize queries employing the expression. JSON_VALUE()
函数和表达式在JSON
列上创建索引,该表达式可用于优化使用该表达式的查询。See the description of that function for more information and examples.有关更多信息和示例,请参阅该函数的说明。
It is also possible to use indirect indexing of JSON columns in MySQL NDB Cluster, subject to the following conditions:也可以在MySQL NDB集群中使用JSON列的间接索引,但需满足以下条件:
NDB
handles a JSON
column value internally as a BLOB
. NDB
将JSON
列值作为BLOB
在内部处理。This means that any 这意味着任何具有一个或多个JSON列的NDB
table having one or more JSON columns must have a primary key, else it cannot be recorded in the binary log.NDB
表都必须具有主键,否则不能记录在二进制日志中。
The NDB
storage engine does not support indexing of virtual columns. NDB
存储引擎不支持虚拟列的索引。Since the default for generated columns is 由于生成列的默认值为VIRTUAL
, you must specify explicitly the generated column to which to apply the indirect index as STORED
.VIRTUAL
列,因此必须显式指定将要应用间接索引的生成列,作为STORED
。
The 用于创建此处显示的表CREATE TABLE
statement used to create the table jempn
shown here is a version of the jemp
table shown previously, with modifications making it compatible with NDB
:jempn
的CREATE TABLE
语句是前面显示的jemp
表的一个版本,经过修改使其与NDB兼容:
CREATE TABLE jempn ( a BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY, c JSON DEFAULT NULL, g INT GENERATED ALWAYS AS (c->"$.name") STORED, INDEX i (g) ) ENGINE=NDB;
We can populate this table using the following 我们可以使用以下INSERT
statement:INSERT
语句填充此表:
INSERT INTO jempn (a, c) VALUES (NULL, '{"id": "1", "name": "Fred"}'), (NULL, '{"id": "2", "name": "Wilma"}'), (NULL, '{"id": "3", "name": "Barney"}'), (NULL, '{"id": "4", "name": "Betty"}');
Now 现在NDB
can use index i
, as shown here:NDB
可以使用索引i
,如下所示:
mysql>EXPLAIN SELECT c->>"$.name" AS name FROM jempn WHERE g > 2\G
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: jempn partitions: p0,p1 type: range possible_keys: i key: i key_len: 5 ref: NULL rows: 3 filtered: 100.00 Extra: Using where with pushed condition (`test`.`jempn`.`g` > 2) 1 row in set, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Note Code: 1003 Message: /* select#1 */ select json_unquote(json_extract(`test`.`jempn`.`c`,'$.name')) AS `name` from `test`.`jempn` where (`test`.`jempn`.`g` > 2) 1 row in set (0.00 sec)
You should keep in mind that a stored generated column uses 您应该记住,存储的生成列使用DataMemory
, and that an index on such a column uses IndexMemory
.DataMemory
,而此类列上的索引使用IndexMemory
。