【原创】MySQL5.7 虚拟列实现表达式索引
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 虚拟列实现表达式索引相关推荐
- mysql5.7+ 虚拟列,json使用初体验
什么是虚拟列? 在MySQL 5.7中,支持两种Generated Column,即Virtual Generated Column和Stored Generated Column,前者只将Gener ...
- mysql动态扩展_动态可扩展查询MYSQL5.7JSON+虚拟列+Mybatis
背景:现有业务扩展字段,都存在feature字段,存在语义不清晰以及,难以利用索引查询问题 Mysql 5.7后推出利器,JSON+虚拟列,即实现了业务语义统一,也支持索引查询加速 一.简单描述 My ...
- Oracle之虚拟列及虚拟列索引
Oracle之虚拟列及虚拟列索引 1. 为什么要使用虚拟列 (1)可以为虚拟列创建索引(oracle为其创建function index) (2)可以搜集虚拟列的统计信息statistics,为CBO ...
- oracle如何查询虚拟列,Oracle11g新特性之--虚拟列(VirtualColumn)
Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...
- Oracle 11g新特性之--虚拟列(Virtual Column)
Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...
- oracle+字段+virtual,Oracle 11g新特性之--虚拟列(Virtual Column)
Oracle 11g新特性之--虚拟列(Virtual Column) Oracle 11G虚拟列Virtual Column介绍 在老的 Oracle 版本,当我们需要使用表达式或者一些计算公式时, ...
- mysql 字段值为 a b c_数据的虚拟列-让数据库中的C字段等于a+b
直接用update aaaaa aa set aa.f = (aa.a+aa.b)就行了 ======================================= 引出来的新知识--虚拟列 虚拟 ...
- MySQL之虚拟列的详细讲解
MySQL 5.7引入了Generated Column,所谓Cenerated Column,就是数据库中的某一列由其他列计算而得.MySQL 5.7中,支持两种Generated Column,即 ...
- 分区表(表分区的具体作用、什么时候需要分区、表分区的优点)、表分区的几种类型及操作方法(range/hash/list/虚拟列/Interval/组合分区)、普通表转分区表的方法、分区表的其它操作
文章目录 分区表(谨慎使用,了解即可) 表空间及分区表的概念 表分区的具体作用 什么时候需要分区 表分区的优点 表分区的几种类型及操作方法 范围分区(range) 哈希分区(hash) 列表分区(li ...
最新文章
- 电脑网络禁用了怎么恢复_网卡禁用怎么启用恢复
- Android动态加载技术初探
- 101. Leetcode 139. 单词拆分 (动态规划-完全背包)
- ActivityGroup中的子Activity创建Dialog:android.view.WindowManager$BadTokenException: U
- 使用SampleGrabber过滤器扑获图像
- 对层级聚类树进行模块分割,定位基因在哪个模块中
- 《并行计算的编程模型》一3.8.3 原子交换和条件交换
- pg_restore - 从一个由 pg_dump 创建的备份文件中恢复 PostgreSQL 数据库。
- sp+Ssh+Mysql实现的简单的企业物资信息管理
- 使用vSphere Power Cli初始化数据中心
- 2020 ECCV 目标检测冠军
- python和c先学哪个-先学C语言还是Python?资深程序员往往是这样建议的!
- 2020-12-04mscomm.ocx注册的问题
- 判断字符串是否是邮箱或者手机号码格式
- 最好用的Mac任务规划软件【滴答清单】
- Panel的基本用法
- zanti html恶搞,Html.AntiForgeryToken 突然报这个错误 太奇怪了
- python俄罗斯方块小游戏实验报告,童年的记忆——如何用python写一个俄罗斯方块小游戏!...
- IDA安卓动调 模拟器手机(详细)
- 开发利器之Mac下的MacPorts
热门文章
- 树莓派python教程_两个简易的树莓派初学者Python程序
- mysql 输出参数赋值_【Mysql 调用存储过程,输出参数的坑】
- 边缘计算架构_边缘计算架构梳理
- php入门的ppt,php学习 字符串课件
- Leetcode周赛5193. 删除字符使字符串变好
- Leetcode7 :整数反转(JAVA)
- 2020年旷世校招JAVA岗笔试第一题
- 【项目管理】绩效域-工件裁剪对照(绩效维度)
- 软考考后常见问题汇总
- 《系统集成项目管理工程师》必背100个知识点-47质量保证人员(QA)的主要工作...