mysql通配符查询 性能_使用mysql5.7新特性解决前通配符查询性能问题
众所周知,在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新特性解决前通配符查询性能问题相关推荐
- MySQL5.6 新特性之GTID【转】
转自 MySQL5.6 新特性之GTID - jyzhou - 博客园 http://www.cnblogs.com/zhoujinyi/p/4717951.html 背景: MySQL5.6在5.5 ...
- 如何保障MySQL主从复制关系的稳定性?关键词(新特性、crash-safe)
一 前言 MySQL 主从架构已经被广泛应用,保障主从复制关系的稳定性是大家一直关注的焦点.MySQL 5.6 针对主从复制稳定性提供了新特性: slave 支持 crash-safe.该功能可以解决 ...
- 盘点 Oracle 11g 中新特性带来的10大性能影响
盘点 Oracle 11g 中新特性带来的10大性能影响 原创 2017-08-02 盖国强 数据和云 Oracle的任何一个新版本,总是会带来大量引人瞩目的新特性,但是往往在这些新特性引入之初,首先 ...
- 鸿蒙系统对手机性能的提升,鸿蒙OS手机版再爆新特性,流畅度和性能大幅提升,用户评价很高...
原标题:鸿蒙OS手机版再爆新特性,流畅度和性能大幅提升,用户评价很高 不受限制地影响真好,但凡是都要有一个循序渐进的过程.华为自从公布鸿蒙OS手机版之后,用户都迫不及待地想体验.如今它真的来了,而且体 ...
- mysql5.7 json特性_【Mysql】Mysql5.7新特性之-json存储
一 写在前面 本系列文章基于 5.7.12 版本讲述MySQL的新特性.从安装,文件结构,SQL ,优化 ,运维层面 复制,GITD等几个方面展开介绍 5.7 的新特性和功能.同时也建议大家跟踪官方b ...
- 【MySQL】MySQL5.6新特性之Index Condition Pushdown
一 概念介绍 Index Condition Pushdown (ICP)是MySQL 5.6 版本中的新特性,是一种在存储引擎层使用索引过滤数据的一种优化方式. a 当关闭ICP时,inde ...
- system.gc 性能_使用这些先进的GC技术提高应用程序性能
system.gc 性能 应用程序性能是我们关注的重点,垃圾收集优化是取得小而有意义的进步的好地方 自动化垃圾收集(与JIT HotSpot编译器一起)是JVM中最先进,最有价值的组件之一,但是许多开 ...
- MySQL 8.0 在关系数据库方面有这些新特性
作者 | 捏造的信仰 原文 | https://segmentfault.com/a/1190000013803247 本文介绍几个 8.0 在关系数据库方面的主要新特性. 你可能已经知道 MySQL ...
- Mysql基础篇(10)—— MySQL8.0新特性概览
新增的新特性 更简便的NoSQL支持. 更好的索引,新增了隐藏索引和降序索引.隐藏索引可以用来去掉索引对查询性能的影响.在查询中混合存在多列索引时,使用降序索引可以提高查询的性能. 更完善的JSON支 ...
最新文章
- NOIP2012 DAY1 T2 国王游戏
- 《Python知识手册》,V3.0版来了,2021年,走起!
- 话里话外:信息资源整合失败之痛(二)
- QCustomplot几种清理曲线数据方法
- HttpServletRequest和@Requestparam、@RequestBody、直接实体接收请求参数的区别与示例
- 分而治之_编写干净的测试–分而治之
- 【Flutter】基础组件【07】Appbar
- C语言实训设计——疫情健康打卡系统
- 什么是静态代理,什么是动态代理
- 办公室计算机打印机共享,办公室共享连接打印机全攻略,办公人必会操作技能...
- python爬虫 微信公众号模拟登陆js解密
- 化工过程开发与工程思维
- mame 游戏铁钩船长/拳皇97 支持多手柄,电视遥控器~~
- 用python扑克随机发牌_Python小应用之发扑克牌
- 关于transform-style:preserve-3d的些许明了
- 【HDOJ】1814 Peaceful Commission
- php 微信创建客服,如何给微信小程序内添加客服按钮
- 莺尾花数据集--kNN分类
- JS字符串格式化函数 string.format
- 建立图书馆书目索引表