您的位置:首页 > 数据库 > MySQL

mysql5.7官网直译优化和索引--使用生成列的索引

2017-12-08 15:14 357 查看
8.3.10 Optimizer Use of Generated Column Indexes 优化使用生成的列的索引

mysql支持索引被产生的列。例如:

CREATE TABLE t1 (f1 INT, gc INT AS (f1 + 1) STORED, INDEX (gc));

被产生的列gc,是表达式f1+1得到的。列被索引并且优化器能够使用该索引在执行计划的构造过程中。在下面的查询中,where条件引用了gc,所以优化器考虑是否有索引在该列上从而生成更有效的执行计划:

SELECT * FROM t1 WHERE gc > 9;

优化器能够使用在被生成的列上的索引来生成执行计划,即使没有按名称对这些列查询,也没有直接引用。在如下的查询中,并没有直接引用gc但是使用的表达式和gc定义匹配:

SELECT * FROM t1 WHERE f1 + 1 > 9;

优化器识别到表达式f1+1和gc的定义匹配并且gc是被索引的,所以它考虑使用索引来产生执行计划。你能看到使用EXPLAIN:

mysql> EXPLAIN SELECT * FROM t1 WHERE f1 + 1 > 9\G

*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: t1

   partitions: NULL

         type: range

possible_keys: gc

          key: gc

      key_len: 5

          ref: NULL

         rows: 1

     filtered: 100.00

        Extra: Using index condition

实际上,优化器通过被产生的列gc来取代了和其匹配的表达式f1+1。很明显得到重写了查询可以在扩展的EXPLAIN信息中查看,通过SHOW WARNINGS:

mysql> SHOW WARNINGS\G

*************************** 1. row ***************************

  Level: Note

   Code: 1003

Message: /* select#1 */ select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`gc`

         AS `gc` from `test`.`t1` where (`test`.`t1`.`gc` > 9)

下面给出优化器要使用被产生的列上的索引的限制和条件:

1)对于一个查询表达式匹配一个被产生的列的定义,表达式必须恒等的且有相同的结果类型。例如,如果产生的列表达式是f1+1,优化器不能识别一个匹配如果查询是1+f1或者是f1+1(一个整数类型)不会匹配一个字符串。

2)优化器能够使用的操作是: =, <, <=, >, >=, BETWEEN, and IN().

   除BETWEEN和IN()之外的操作数,任何数都可以和被产生的列匹配。对于BETWEEN和IN().只有第一个参数能够被取代通过匹配被产生的列。并且其他参数必须有相同的结果类型。BETWEEN和IN()依然没有得到支持关于JSON值的对比。

3)被产生的列必须被定义为一个表达式,其中至少一个函数被调用,或者操作数被提名在之前的项目中。表达式不能由其他列的简单引用组成。例如,gc INT as (f1) SORTED 组成仅仅是一个列的引用,所以索引在gc列上不会被考虑。

4)对于比较字符串类型的被产生的列,其中比较的值来自JSON函数,返回一个被引用的字符串,JSON_UNQUOTE()被需要再列的定义去移除各位的引用从函数值中。(对于直接比较一个字符串和函数结果,JSON比较处理去掉引用,但是这不会引起索引查询)例如,写一个列定义如下:

doc_name TEXT AS (JSON_EXTRACT(jdoc, '$.name')) STORED

写它像这样:

doc_name TEXT AS (JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name'))) STORED

通过后者的定义,优化器能够查明对于如下两种比较:

... WHERE JSON_EXTRACT(jdoc, '$.name') = 'some_string' ...

... WHERE JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name')) = 'some_string' ...

没有JSON_UNQUOTE()在列定义中,优化器查明的匹配只有第一个这种的表达式。

5)如果优化器没有选择希望的索引,一个索引提示能够强制优化器使用从而给出一个不同的选择。

到此关于索引和优化的介绍就结束了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息