CREATE TABLE Statement 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. 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. 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. Adding or dropping a secondary index on a virtual column is an in-place operation. As noted elsewhere,  JSON  columns cannot be indexed directly. 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 2588 Indexing a Generated Column to Provide a JSON Column Index