MySQL支持对生成的列进行索引。例如:
创建表t1 (f1 INT, gc INT AS (f1 + 1) STORED, INDEX (gc));
生成的列,gc
,定义为表达式F1 + 1
.列也被索引,优化器可以在构建执行计划时考虑该索引。在下面的查询中,在哪里
从句指gc
优化器会考虑该列的索引是否会产生更有效的计划:
SELECT FROM t1 WHERE gc > 9;
优化器可以在生成的列上使用索引来生成执行计划,即使在查询中没有按名称直接引用这些列的情况下也是如此。这种情况发生在在哪里
,命令
,或集团
子句引用与某些生成的索引列的定义匹配的表达式。下面的查询不直接引用gc
但确实使用了与定义相匹配的表达式gc
:
SELECT * FROM t1 WHERE f1 + 1 > 9;
优化器识别表达式F1 + 1
符合gc
这gc
被索引,因此它在执行计划构建期间考虑该索引。你可以看到这个用法解释
:
mysql >解释SELECT * FROM t1 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:使用索引条件
实际上,优化器已经替换了表达式F1 + 1
使用与表达式匹配的生成列的名称。这在扩展中可用的重写查询中也很明显解释
显示的信息显示警告
:
mysql > \ G显示警告 *************************** 1。行 *************************** 水平:注意代码:1003信息:/ *选择# 1 * /选择“测试”,“t1”。' f1 ' AS ' f1 ', ' test ' . ' t1 '。' gc ' AS ' gc ' from ' test '。' t1 ' where (' test ' . ' t1 ' .)“gc”>
以下限制和条件适用于优化器对生成的列索引的使用:
要使查询表达式与生成的列定义匹配,表达式必须相同,并且必须具有相同的结果类型。例如,如果生成的列表达式为
F1 + 1
,如果查询使用,优化器不会识别匹配1 + f1
,或如果F1 + 1
(整数表达式)与字符串进行比较。优化适用于以下操作符:
=
,<
,< =
,>
,> =
,之间的
,在()
.对于其他操作人员
之间的
而且在()
,任一操作数都可以被匹配生成的列替换。为之间的
而且在()
,只有第一个参数可以被匹配的生成列替换,其他参数必须具有相同的结果类型。之间的
而且在()
还不支持涉及JSON值的比较。生成的列必须定义为至少包含一个函数调用或上一项中提到的操作符之一的表达式。表达式不能由对另一列的简单引用组成。例如,
gc INT AS (f1)存储
仅由列引用组成,因此上的索引gc
不被考虑。为了将字符串与生成的索引列进行比较,这些索引列从返回引号字符串的JSON函数中计算值,
JSON_UNQUOTE ()
列定义中需要从函数值中删除额外的引号。(对于字符串与函数结果的直接比较,JSON比较器处理引号删除,但这不会发生在索引查找中。)例如,不要写这样的列定义:doc_name TEXT AS (JSON_EXTRACT(jdoc, '$.name'))已存储
这样写:
doc_name TEXT AS (JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name')))已存储
使用后一种定义,优化器可以检测到这两个比较的匹配:
...WHERE JSON_EXTRACT(jdoc, '$.name') = 'some_string... ...WHERE JSON_UNQUOTE(JSON_EXTRACT(jdoc, '$.name')) = 'some_string“…
没有
JSON_UNQUOTE ()
在列定义中,优化器仅为第一个比较检测匹配。如果优化器未能选择所需的索引,则可以使用索引提示强制优化器做出不同的选择。