MySQL自古以来就不提供函数索引这么复杂的功能。那怎么在MySQL里面实现这样的功能呢? 我们先来看看函数索引的概念。函数索引,也可称为表达式索引,也就是基于字段以特定函数(表达式)建立索引来提升查询性能之需。函数索引的优势在于更加精确的获取所需要的数据。

MySQL 5.7提供了一个新的特性,虚拟列,可以很完美的解决这个问题。

在介绍虚拟列之前,我们来看看在MySQL里面普通索引的范例。

示例表结构:

CREATE TABLE t1 (id INT ,rank INT, log_time DATETIME, nickname VARCHAR(64)) ENGINE INNODB;
ALTER TABLE t1 ADD PRIMARY KEY (id), ADD KEY idx_rank (rank),ADD KEY idx_log_time (log_time);

示例表数据量,这里我增加了5000条记录:

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
|     5000 |
+----------+
1 row in set (0.00 sec)

假设我们来检索2015年4月9号的数据。(结果是有两条记录,id 分别为95和3423。)

mysql> SELECT * FROM t1 WHERE DATE(log_time) = '2015-04-09'\G
*************************** 1. row ***************************id: 95rank: 24
log_time: 2015-04-09 05:53:13
nickname: test
*************************** 2. row ***************************id: 3423rank: 42
log_time: 2015-04-09 02:55:38
nickname: test
2 rows in set (0.01 sec)

下来我们看看这条语句的查询计划。

mysql> explain SELECT * FROM t1 WHERE DATE(log_time) = '2015-04-09'\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t1partitions: NULLtype: ALL
possible_keys: NULLkey: NULLkey_len: NULLref: NULLrows: 5000filtered: 100.00Extra: Using where
1 row in set, 1 warning (0.00 sec)

我们发现TYPE是ALL,扫描的函数是5000,也就是说这条语句进行了一个全表扫描。 虽然给字段log_time 加了索引,但是没有用到,那这个时候怎么办?

在MySQL里面一般这样修改:

mysql> SELECT * FROM t1 WHERE log_time >= '2015-04-09 00:00:00' AND log_time <='2015-04-10 00:00:00'\G
*************************** 1. row ***************************id: 3423rank: 42
log_time: 2015-04-09 02:55:38
nickname: test
*************************** 2. row ***************************id: 95rank: 24
log_time: 2015-04-09 05:53:13
nickname: test
2 rows in set (0.00 sec)

通过查询结果,发现结果集一致,那再来看看查询计划

mysql> explain SELECT * FROM t1 WHERE log_time >= '2015-04-09 00:00:00' AND log_time <= '2015-04-10 00:00:00'\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t1partitions: NULLtype: range
possible_keys: idx_log_timekey: idx_log_timekey_len: 6ref: NULLrows: 2filtered: 100.00Extra: Using index condition
1 row in set, 1 warning (0.00 sec)

可以看到这条修改过的语句很好的利用到了idx_log_time这条索引。

那好,这个是之前在MySQL 5.6以及之前的旧版本解决方法,随着MySQL 5.7的发布,虚拟列的出现让这个问题更加简单。

现在修改下之前的表结构:

ALTER TABLE t1 ADD COLUMN log_date  DATE AS (DATE(log_Time)) stored, ADD KEY idx_log_date (log_date);

这样,增加了一新列,用来存放date(log_time)这个表达式,并且给他加了一列索引。

那么,之前的语句就变成如下:

mysql> SELECT * FROM t1 WHERE log_date = '2015-04-09'\G
*************************** 1. row ***************************id: 95rank: 24
log_time: 2015-04-09 05:53:13
nickname: test
log_date: 2015-04-09
*************************** 2. row ***************************id: 3423rank: 42
log_time: 2015-04-09 02:55:38
nickname: test
log_date: 2015-04-09
2 rows in set (0.00 sec)

执行后结果集和之前的一致。

我们来看看查询计划,发现很好的利用了idx_log_date索引列。

mysql> explain  SELECT * FROM t1 WHERE log_date = '2015-04-09'\G
*************************** 1. row ***************************id: 1select_type: SIMPLEtable: t1partitions: NULLtype: ref
possible_keys: idx_log_datekey: idx_log_datekey_len: 4ref: constrows: 2filtered: 100.00Extra: NULL
1 row in set, 1 warning (0.00 sec)

通过以上介绍,我们看到虚拟列实现起来相对之前的方法来的容易的多。但是这里笔者还是得说上几句。

函数索引的用法以及SQL语句虽然写起来简单,但是在大部分场合下,只能说不得已而为之,是一种设计上的缺陷,后期增加了运维人员的运维难度以及繁琐度。这也就是为什么MySQL 直到5.7才推出了这项类似的功能的原因。

【原创】MySQL5.7 虚拟列实现表达式索引相关推荐

  1. mysql5.7+ 虚拟列,json使用初体验

    什么是虚拟列? 在MySQL 5.7中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column,前者只将Gener ...

  2. mysql动态扩展_动态可扩展查询MYSQL5.7JSON+虚拟列+Mybatis

    背景:现有业务扩展字段,都存在feature字段,存在语义不清晰以及,难以利用索引查询问题 Mysql 5.7后推出利器,JSON+虚拟列,即实现了业务语义统一,也支持索引查询加速 一.简单描述 My ...

  3. Oracle之虚拟列及虚拟列索引

    Oracle之虚拟列及虚拟列索引 1. 为什么要使用虚拟列 (1)可以为虚拟列创建索引(oracle为其创建function index) (2)可以搜集虚拟列的统计信息statistics,为CBO ...

  4. oracle如何查询虚拟列,Oracle11g新特性之--虚拟列(VirtualColumn)

    Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...

  5. Oracle 11g新特性之--虚拟列(Virtual Column)

    Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...

  6. oracle+字段+virtual,Oracle 11g新特性之--虚拟列(Virtual Column)

    Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...

  7. mysql 字段值为 a b c_数据的虚拟列-让数据库中的C字段等于a+b

    直接用update aaaaa aa set aa.f = (aa.a+aa.b)就行了 ======================================= 引出来的新知识--虚拟列 虚拟 ...

  8. MySQL之虚拟列的详细讲解

    MySQL 5.7引入了Generated Column,所谓Cenerated Column,就是数据库中的某一列由其他列计算而得.MySQL 5.7中,支持两种Generated Column,即 ...

  9. 分区表(表分区的具体作用、什么时候需要分区、表分区的优点)、表分区的几种类型及操作方法(range/hash/list/虚拟列/Interval/组合分区)、普通表转分区表的方法、分区表的其它操作

    文章目录 分区表(谨慎使用,了解即可) 表空间及分区表的概念 表分区的具体作用 什么时候需要分区 表分区的优点 表分区的几种类型及操作方法 范围分区(range) 哈希分区(hash) 列表分区(li ...

最新文章

  1. 电脑网络禁用了怎么恢复_网卡禁用怎么启用恢复
  2. Android动态加载技术初探
  3. 101. Leetcode 139. 单词拆分 (动态规划-完全背包)
  4. ActivityGroup中的子Activity创建Dialog:android.view.WindowManager$BadTokenException: U
  5. 使用SampleGrabber过滤器扑获图像
  6. 对层级聚类树进行模块分割,定位基因在哪个模块中
  7. 《并行计算的编程模型》一3.8.3 原子交换和条件交换
  8. pg_restore - 从一个由 pg_dump 创建的备份文件中恢复 PostgreSQL 数据库。
  9. sp+Ssh+Mysql实现的简单的企业物资信息管理
  10. 使用vSphere Power Cli初始化数据中心
  11. 2020 ECCV 目标检测冠军
  12. python和c先学哪个-先学C语言还是Python?资深程序员往往是这样建议的!
  13. 2020-12-04mscomm.ocx注册的问题
  14. 判断字符串是否是邮箱或者手机号码格式
  15. 最好用的Mac任务规划软件【滴答清单】
  16. Panel的基本用法
  17. zanti html恶搞,Html.AntiForgeryToken 突然报这个错误 太奇怪了
  18. python俄罗斯方块小游戏实验报告,童年的记忆——如何用python写一个俄罗斯方块小游戏!...
  19. IDA安卓动调 模拟器手机(详细)
  20. 开发利器之Mac下的MacPorts

热门文章

  1. 树莓派python教程_两个简易的树莓派初学者Python程序
  2. mysql 输出参数赋值_【Mysql 调用存储过程,输出参数的坑】
  3. 边缘计算架构_边缘计算架构梳理
  4. php入门的ppt,php学习 字符串课件
  5. Leetcode周赛5193. 删除字符使字符串变好
  6. Leetcode7 :整数反转(JAVA)
  7. 2020年旷世校招JAVA岗笔试第一题
  8. 【项目管理】绩效域-工件裁剪对照(绩效维度)
  9. 软考考后常见问题汇总
  10. 《系统集成项目管理工程师》必背100个知识点-47质量保证人员(QA)的主要工作...