众所周知,在mysql里的后通配符可以使用索引查找,前通配查询却无法使用到索引,即使是使用到了索引,也是使用了索引全扫描,效率依然不高,再MySQL5.7之前,一直都没有好的办法解决,但是到了MySQL5.7,自从有了虚拟列,这个问题就好办多了,能够已空间换时间。

创建测试表

root@localhost [zeno]>show create tabletest_user\G ;*************************** 1. row ***************************

Table: test_userCreate Table: CREATE TABLE`test_user` (

`uid`int(11) NOT NULLAUTO_INCREMENT,

`name`varchar(32) DEFAULT NULL,

`add_time`datetime DEFAULT NULL,PRIMARY KEY(`uid`),KEY`ix_name` (`name`)

) ENGINE=InnoDB AUTO_INCREMENT=6037060 DEFAULT CHARSET=utf81 row in set (0.00sec)

ERROR:

No query specified

使用python插入测试数据

#!/usr/bin/python

importstringimportrandomimportMySQLdbimporttime

conn= MySQLdb.connect(host='IPAddr',

port=3306,

user='zeno',

passwd='zeno',

db='zeno')definsert(para):

i= 11

whileTrue:

r_name= ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(10, 30)))printr_name

cursor=conn.cursor()

cursor.execute("INSERT INTO test_user (name,add_time) VALUES ('%s', now())" %str(r_name))

i= i + 1conn.commit()#time.sleep(0.1)

printi

insert(conn)

查看插入的数据量

root@localhost [zeno]>show table status like 'test_user'\G ;*************************** 1. row ***************************Name: test_user

Engine: InnoDB

Version:10Row_format: Dynamic

Rows:6002441Avg_row_length:51Data_length:310165504Max_data_length:0Index_length:0Data_free:5242880Auto_increment:6037060Create_time:2017-11-23 16:25:15Update_time:2017-11-23 16:23:29Check_time:NULLCollation: utf8_general_ci

Checksum:NULLCreate_options:

Comment:1 row in set (0.00sec)

ERROR:

No query specified

root@localhost [zeno]>select * from test_user limit 10;+-----+-------------------------------+---------------------+

| uid | name | add_time |

+-----+-------------------------------+---------------------+

| 1 | U0WUJ3JJ81IRP27BSA4471 | 2017-11-23 15:37:49 |

| 2 | SOLYNM9Q9A5Y94YG | 2017-11-23 15:37:49 |

| 3 | ONNU5PPKXC3GBR | 2017-11-23 15:37:49 |

| 4 | WVC6GOJ29C | 2017-11-23 15:37:49 |

| 5 | Z653X99ZZI | 2017-11-23 15:37:49 |

| 6 | YP92P02DIKQ8O66K | 2017-11-23 15:37:49 |

| 7 | 2X3G6H8849SDP | 2017-11-23 15:37:49 |

| 8 | 9N9F668XQMTRQSCNE0FWJBMMJEFC0 | 2017-11-23 15:37:50 |

| 9 | 15XAHWZ1IJBP6P4EKCH | 2017-11-23 15:37:50 |

| 10 | VHQJQGQC7U | 2017-11-23 15:37:50 |

+-----+-------------------------------+---------------------+

10 rows in set (0.00 sec)

开始测试

一、验证查询条件中使用后通配符的情况

root@localhost [zeno]>select * from test_user where name like '9N9F668XQ%';+-----+-------------------------------+---------------------+

| uid | name | add_time |

+-----+-------------------------------+---------------------+

| 8 | 9N9F668XQMTRQSCNE0FWJBMMJEFC0 | 2017-11-23 15:37:50 |

+-----+-------------------------------+---------------------+

1 row in set (0.00sec)

root@localhost [zeno]>explain select * from test_user where name like '9N9F668XQ%';+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

| 1 | SIMPLE | test_user | NULL | range | ix_name | ix_name | 99 | NULL | 1 | 100.00 | Using index condition |

+----+-------------+-----------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

1 row in set, 1 warning (0.00 sec)

600W的数据,执行时间0.00sec,已经是毫秒级查询了

从执行计划中可以看出,type=range, key = 'ix_name',证明是对索引ix_name进行了范围查找,所以,能很快地得到结果

二、验证查询条件中使用前通配符的情况

root@localhost [zeno]>select * from test_user where name like '%WJBMMJEFC0';+-----+-------------------------------+---------------------+

| uid | name | add_time |

+-----+-------------------------------+---------------------+

| 8 | 9N9F668XQMTRQSCNE0FWJBMMJEFC0 | 2017-11-23 15:37:50 |

+-----+-------------------------------+---------------------+

1 row in set (3.84sec)

root@localhost [zeno]>explain select * from test_user where name like '%WJBMMJEFC0';+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+

| 1 | SIMPLE | test_user | NULL | ALL | NULL | NULL | NULL | NULL | 6002441 | 11.11 | Using where |

+----+-------------+-----------+------------+------+---------------+------+---------+------+---------+----------+-------------+

1 row in set, 1 warning (0.00 sec)

600万的数据,运行了3.84sec,速度非常慢

从执行计划中type=‘ALL’可以看出是进行了全表扫描,扫描完之后,再根据where条件找出合适的数据

在MySQL5.7之前,对于这种条件中使用了前通配符的查询,几乎就是束手无策,但是,MySQL5.7中增加了一项新功能,可以用较小的代价实现快速查询

创建虚拟列

root@localhost [zeno]>alter table test_user add r_name varchar(32) generated always as (reverse(`name`));

Query OK,0 rows affected (0.44sec)

Records:0 Duplicates: 0 Warnings: 0

在虚拟列上创建索引(跟一般创建索引无异)

root@localhost [zeno]>create index ix_r_name ontest_user(r_name) ;

Query OK,0 rows affected (41.90sec)

Records:0 Duplicates: 0 Warnings: 0

问题来了,已经创建了虚拟列,也创建了所以,怎么实现对前通配符的快速查询呢?

先用一个简短的数字来说明一下思路:假设要查询的列的最终值为‘0123456789’,前通配查询的时候,条件是 name like '%6789',但是已经创建了虚拟列,虚拟列的效果是把原来的数据反转,也就是变成了‘9876543210’,那么,查询的条件变成了name like '9876%',但是,不可能是每次都要自己计算一下,把'6789'换成‘9876’

因此,在查询的时候,还要取巧的一步,条件中再次把输入的值反转,结果如下

root@localhost [zeno]>select * from test_user where r_name like concat(reverse('WJBMMJEFC0'),'%');+-----+-------------------------------+---------------------+-------------------------------+

| uid | name | add_time | r_name |

+-----+-------------------------------+---------------------+-------------------------------+

| 8 | 9N9F668XQMTRQSCNE0FWJBMMJEFC0 | 2017-11-23 15:37:50 | 0CFEJMMBJWF0ENCSQRTMQX866F9N9 |

+-----+-------------------------------+---------------------+-------------------------------+

1 row in set (0.00sec)

root@localhost [zeno]>explain select * from test_user where r_name like concat(reverse('WJBMMJEFC0'),'%');+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |

+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+

| 1 | SIMPLE | test_user | NULL | range | ix_r_name | ix_r_name | 99 | NULL | 1 | 100.00 | Using where |

+----+-------------+-----------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00 sec)

从执行结果来看,效果已经达到了,600W的数据也只是执行了0.00sec

三、在条件中同时使用了前通配符和后通配符的情况,暂时没有好的解决办法

参考文档:

MySQL官方介绍虚拟列:https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html

以上,如有错谬,请不吝指正。

原创作品,如需转载,请标明出处,谢谢~

mysql通配符查询 性能_使用mysql5.7新特性解决前通配符查询性能问题相关推荐

  1. MySQL5.6 新特性之GTID【转】

    转自 MySQL5.6 新特性之GTID - jyzhou - 博客园 http://www.cnblogs.com/zhoujinyi/p/4717951.html 背景: MySQL5.6在5.5 ...

  2. 如何保障MySQL主从复制关系的稳定性?关键词(新特性、crash-safe)

    一 前言 MySQL 主从架构已经被广泛应用,保障主从复制关系的稳定性是大家一直关注的焦点.MySQL 5.6 针对主从复制稳定性提供了新特性: slave 支持 crash-safe.该功能可以解决 ...

  3. 盘点 Oracle 11g 中新特性带来的10大性能影响

    盘点 Oracle 11g 中新特性带来的10大性能影响 原创 2017-08-02 盖国强 数据和云 Oracle的任何一个新版本,总是会带来大量引人瞩目的新特性,但是往往在这些新特性引入之初,首先 ...

  4. 鸿蒙系统对手机性能的提升,鸿蒙OS手机版再爆新特性,流畅度和性能大幅提升,用户评价很高...

    原标题:鸿蒙OS手机版再爆新特性,流畅度和性能大幅提升,用户评价很高 不受限制地影响真好,但凡是都要有一个循序渐进的过程.华为自从公布鸿蒙OS手机版之后,用户都迫不及待地想体验.如今它真的来了,而且体 ...

  5. mysql5.7 json特性_【Mysql】Mysql5.7新特性之-json存储

    一 写在前面 本系列文章基于 5.7.12 版本讲述MySQL的新特性.从安装,文件结构,SQL ,优化 ,运维层面 复制,GITD等几个方面展开介绍 5.7 的新特性和功能.同时也建议大家跟踪官方b ...

  6. 【MySQL】MySQL5.6新特性之Index Condition Pushdown

    一 概念介绍     Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. a 当关闭ICP时,inde ...

  7. system.gc 性能_使用这些先进的GC技术提高应用程序性能

    system.gc 性能 应用程序性能是我们关注的重点,垃圾收集优化是取得小而有意义的进步的好地方 自动化垃圾收集(与JIT HotSpot编译器一起)是JVM中最先进,最有价值的组件之一,但是许多开 ...

  8. MySQL 8.0 在关系数据库方面有这些新特性

    作者 | 捏造的信仰 原文 | https://segmentfault.com/a/1190000013803247 本文介绍几个 8.0 在关系数据库方面的主要新特性. 你可能已经知道 MySQL ...

  9. Mysql基础篇(10)—— MySQL8.0新特性概览

    新增的新特性 更简便的NoSQL支持. 更好的索引,新增了隐藏索引和降序索引.隐藏索引可以用来去掉索引对查询性能的影响.在查询中混合存在多列索引时,使用降序索引可以提高查询的性能. 更完善的JSON支 ...

最新文章

  1. NOIP2012 DAY1 T2 国王游戏
  2. 《Python知识手册》,V3.0版来了,2021年,走起!
  3. 话里话外:信息资源整合失败之痛(二)
  4. QCustomplot几种清理曲线数据方法
  5. HttpServletRequest和@Requestparam、@RequestBody、直接实体接收请求参数的区别与示例
  6. 分而治之_编写干净的测试–分而治之
  7. 【Flutter】基础组件【07】Appbar
  8. C语言实训设计——疫情健康打卡系统
  9. 什么是静态代理,什么是动态代理
  10. 办公室计算机打印机共享,办公室共享连接打印机全攻略,办公人必会操作技能...
  11. python爬虫 微信公众号模拟登陆js解密
  12. 化工过程开发与工程思维
  13. mame 游戏铁钩船长/拳皇97 支持多手柄,电视遥控器~~
  14. 用python扑克随机发牌_Python小应用之发扑克牌
  15. 关于transform-style:preserve-3d的些许明了
  16. 【HDOJ】1814 Peaceful Commission
  17. php 微信创建客服,如何给微信小程序内添加客服按钮
  18. 莺尾花数据集--kNN分类
  19. JS字符串格式化函数 string.format
  20. 建立图书馆书目索引表

热门文章

  1. Apple 远程推送APNS 服务
  2. python中获取当前所有的logger
  3. Site Definition和Web Template的区别
  4. [阅读笔记] Java 7 新特性
  5. 我的Ubuntu体验
  6. (七)全半角转换(转)
  7. 爬虫之proxy(代理)
  8. tomcat的缺少tcnative-1.dll的解决
  9. springmvc 配置和spring配置?
  10. NET中MSMQ的使用----附例子