diff --git a/sql-statements/sql-statement-create-index.md b/sql-statements/sql-statement-create-index.md index 2211011be0ddd..91ca862705fdb 100644 --- a/sql-statements/sql-statement-create-index.md +++ b/sql-statements/sql-statement-create-index.md @@ -6,7 +6,7 @@ aliases: ['/docs/dev/sql-statements/sql-statement-create-index/','/docs/dev/refe # CREATE INDEX -This statement adds a new index to an existing table. It is an alternative syntax to `ALTER TABLE .. ADD INDEX`, and included for MySQL compatibility. +This statement adds a new index to an existing table. It is an alternative syntax to [`ALTER TABLE .. ADD INDEX`](/sql-statements/sql-statement-alter-table.md), and included for MySQL compatibility. ## Synopsis @@ -106,28 +106,26 @@ Query OK, 0 rows affected (0.31 sec) In some scenarios, the filtering condition of a query is based on a certain expression. In these scenarios, the query performance is relatively poor because ordinary indexes cannot take effect, the query can only be executed by scanning the entire table. The expression index is a type of special index that can be created on an expression. Once an expression index is created, TiDB can use the index for the expression-based query, which significantly improves the query performance. -For example, if you want to create an index based on `lower(col1)`, execute the following SQL statement: - -{{< copyable "sql" >}} +For example, if you want to create an index based on `LOWER(col1)`, execute the following SQL statement: ```sql -CREATE INDEX idx1 ON t1 ((lower(col1))); +CREATE INDEX idx1 ON t1 ((LOWER(col1))); ``` Or you can execute the following equivalent statement: -{{< copyable "sql" >}} - ```sql -ALTER TABLE t1 ADD INDEX idx1((lower(col1))); +ALTER TABLE t1 ADD INDEX idx1((LOWER(col1))); ``` You can also specify the expression index when you create the table: -{{< copyable "sql" >}} - ```sql -CREATE TABLE t1(col1 char(10), col2 char(10), index((lower(col1)))); +CREATE TABLE t1 ( + col1 CHAR(10), + col2 CHAR(10), + INDEX ((LOWER(col1))) +); ``` > **Note:** @@ -136,8 +134,6 @@ CREATE TABLE t1(col1 char(10), col2 char(10), index((lower(col1)))); You can drop an expression index in the same way as dropping an ordinary index: -{{< copyable "sql" >}} - ```sql DROP INDEX idx1 ON t1; ``` @@ -145,17 +141,15 @@ DROP INDEX idx1 ON t1; Expression index involves various kinds of expressions. To ensure correctness, only some fully tested functions are allowed for creating an expression index. This means that only these functions are allowed in expressions in a production environment. You can get these functions by querying the `tidb_allow_function_for_expression_index` variable. Currently, the allowed functions are as follows: ``` -json_array, json_array_append, json_array_insert, json_contains, json_contains_path, json_depth, json_extract, json_insert, json_keys, json_length, json_merge_patch, json_merge_preserve, json_object, json_pretty, json_quote, json_remove, json_replace, json_search, json_set, json_storage_size, json_type, json_unquote, json_valid, lower, md5, reverse, tidb_shard, upper, vitess_hash +JSON_ARRAY, JSON_ARRAY_APPEND, JSON_ARRAY_INSERT, JSON_CONTAINS, JSON_CONTAINS_PATH, JSON_DEPTH, JSON_EXTRACT, JSON_INSERT, JSON_KEYS, JSON_LENGTH, JSON_MERGE_PATCH, JSON_MERGE_PRESERVE, JSON_OBJECT, JSON_PRETTY, JSON_QUOTE, JSON_REMOVE, JSON_REPLACE, JSON_SEARCH, JSON_SET, JSON_STORAGE_SIZE, JSON_TYPE, JSON_UNQUOTE, JSON_VALID, LOWER, MD5, REVERSE, TIDB_SHARD, UPPER, VITESS_HASH ``` -For the functions that are not included in the above list, those functions are not fully tested and not recommended for a production environment, which can be seen as experimental. Other expressions such as operators, `cast`, and `case when` are also seen as experimental and not recommended for production. +For the functions that are not included in the above list, those functions are not fully tested and not recommended for a production environment, which can be seen as experimental. Other expressions such as operators, `CAST`, and `CASE WHEN` are also seen as experimental and not recommended for production. If you still want to use those expressions, you can make the following configuration in the [TiDB configuration file](/tidb-configuration-file.md#allow-expression-index-new-in-v400): -{{< copyable "sql" >}} - ```sql allow-expression-index = true ``` @@ -168,63 +162,55 @@ allow-expression-index = true > > The expression in an expression index cannot contain the following content: > -> - Volatile functions, such as `rand()` and `now()`. -> - System variables and user variables. +> - Volatile functions, such as `RAND()` and `NOW()`. +> - [System variables](/system-variables.md) and [user variables](/user-defined-variables.md). > - Subqueries. -> - `AUTO_INCREMENT` column. You can remove this restriction by setting the value of `tidb_enable_auto_increment_in_generated` (system variable) to `true`. -> - Window functions. -> - ROW functions, such as `create table t (j json, key k (((j,j))));`. -> - Aggregate functions. +> - [`AUTO_INCREMENT`](/auto-increment.md) columns. You can remove this restriction by setting the value of [`tidb_enable_auto_increment_in_generated`](/system-variables.md#tidb_enable_auto_increment_in_generated) (system variable) to `true`. +> - [Window functions](/functions-and-operators/window-functions.md). +> - ROW functions, such as `CREATE TABLE t (j JSON, INDEX k (((j,j))));`. +> - [Aggregate functions](/functions-and-operators/aggregate-group-by-functions.md). > > An expression index implicitly takes up a name (for example, `_V$_{index_name}_{index_offset}`). If you try to create a new expression index with the name that a column has already had, an error occurs. In addition, if you add a new column with the same name, an error also occurs. > > Make sure that the number of function parameters in the expression of an expression index is correct. > -> When the expression of an index contains a string-related function, affected by the returned type and the length, creating the expression index might fail. In this situation, you can use the `cast()` function to explicitly specify the returned type and the length. For example, to create an expression index based on the `repeat(a, 3)` expression, you need to modify this expression to `cast(repeat(a, 3) as char(20))`. +> When the expression of an index contains a string-related function, affected by the returned type and the length, creating the expression index might fail. In this situation, you can use the `CAST()` function to explicitly specify the returned type and the length. For example, to create an expression index based on the `REPEAT(a, 3)` expression, you need to modify this expression to `CAST(REPEAT(a, 3) AS CHAR(20))`. When the expression in a query statement matches the expression in an expression index, the optimizer can choose the expression index for the query. In some cases, the optimizer might not choose an expression index depending on statistics. In this situation, you can force the optimizer to select an expression index by using optimizer hints. -In the following examples, suppose that you create the expression index `idx` on the expression `lower(col1)`: +In the following examples, suppose that you create the expression index `idx` on the expression `LOWER(col1)`: If the results of the query statement are the same expressions, the expression index applies. Take the following statement as an example: -{{< copyable "sql" >}} - ```sql -SELECT lower(col1) FROM t; +SELECT LOWER(col1) FROM t; ``` If the same expression is included in the filtering conditions, the expression index applies. Take the following statements as an example: -{{< copyable "sql" >}} - ```sql -SELECT * FROM t WHERE lower(col1) = "a"; -SELECT * FROM t WHERE lower(col1) > "a"; -SELECT * FROM t WHERE lower(col1) BETWEEN "a" AND "b"; -SELECT * FROM t WHERE lower(col1) in ("a", "b"); -SELECT * FROM t WHERE lower(col1) > "a" AND lower(col1) < "b"; -SELECT * FROM t WHERE lower(col1) > "b" OR lower(col1) < "a"; +SELECT * FROM t WHERE LOWER(col1) = "a"; +SELECT * FROM t WHERE LOWER(col1) > "a"; +SELECT * FROM t WHERE LOWER(col1) BETWEEN "a" AND "b"; +SELECT * FROM t WHERE LOWER(col1) IN ("a", "b"); +SELECT * FROM t WHERE LOWER(col1) > "a" AND LOWER(col1) < "b"; +SELECT * FROM t WHERE LOWER(col1) > "b" OR LOWER(col1) < "a"; ``` When the queries are sorted by the same expression, the expression index applies. Take the following statement as an example: -{{< copyable "sql" >}} - ```sql -SELECT * FROM t ORDER BY lower(col1); +SELECT * FROM t ORDER BY LOWER(col1); ``` If the same expression is included in the aggregate (`GROUP BY`) functions, the expression index applies. Take the following statements as an example: -{{< copyable "sql" >}} - ```sql -SELECT max(lower(col1)) FROM t; -SELECT min(col1) FROM t GROUP BY lower(col1); +SELECT MAX(LOWER(col1)) FROM t; +SELECT MIN(col1) FROM t GROUP BY LOWER(col1); ``` -To see the expression corresponding to the expression index, execute `show index`, or check the system tables `information_schema.tidb_indexes` and the table `information_schema.STATISTICS`. The `Expression` column in the output indicates the corresponded expression. For the non-expression indexes, the column shows `NULL`. +To see the expression corresponding to the expression index, execute [`SHOW INDEX`](/sql-statements/sql-statement-show-indexes.md), or check the system tables [`information_schema.tidb_indexes`](/information-schema/information-schema-tidb-indexes.md) and the table [`information_schema.STATISTICS`](/information-schema/information-schema-statistics.md). The `Expression` column in the output indicates the corresponded expression. For the non-expression indexes, the column shows `NULL`. The cost of maintaining an expression index is higher than that of maintaining other indexes, because the value of the expression needs to be calculated whenever a row is inserted or updated. The value of the expression is already stored in the index, so this value does not require recalculation when the optimizer selects the expression index. @@ -246,7 +232,7 @@ Multi-valued indexes are a kind of secondary index defined on an array column. I ### Create multi-valued indexes -You can create multi-valued indexes by using the `CAST(... AS ... ARRAY)` expression in the index definition, as creating an expression index. +You can create multi-valued indexes by using the [`CAST(... AS ... ARRAY)`](/functions-and-operators/cast-functions-and-operators.md) expression in the index definition, as creating an expression index. ```sql mysql> CREATE TABLE customers (