MySQL 11 怎么给字符串字段加索引?
场景引入
假设现在维护一个支持邮箱登录的系统,用户表定义如下:
create table SUser(ID bigint unsigned primary key,email varchar(64), ... )engine=innodb;
由于登录方式为邮箱,那么一定会有下面这样的业务:
select f1,f2 from SUser where email='xxx';
对于上述语句,可以不对email字段加索引,也可以对email建立普通索引,还可以建立前缀索引。其建立索引的语句为:
alter table SUser add index index1(email);
alter table SUser add index index2(email(6));
这两种不同建立方式在数据结构和存储上的区别如下:


由于前缀索引只取规定字节数,所以占用空间更小。
但使用前缀索引可能会增加额外的记录扫描次数。比如要执行下面这个查询:
select id,name,email from SUser where email='zhangssxyz@xxx.com'
如果使用普通索引,执行顺序为:
从index1索引树找到满足条件的记录,取得主键为ID2;
在主键索引树上找到对应的行,如果email值正确,将这行记录加入结果集;
从index1索引树上查找下一条记录,发现不满足条件,结束。
由于只回主键索引取一次数据,所以系统认为只扫描一行。
如果使用前缀索引,执行顺序为:
从index2索引树找到满足条件的记录,第一个是ID1;
在主键索引树上找到对应的行,发现email值不正确,丢弃这行记录;
从index2索引树找到满足条件的下一条记录,取得主键为ID2;
在主键索引树上找到对应的行,如果email值正确,将这行记录加入结果集;
重复上述步骤,直到index2上匹配不到正确的前缀。
这个过程需要回主键索引取4次数据,即扫描了4行。
但是,在该场景下,如果定义的index2为email(7),会发现在index2上能直接取到ID2,也就只需要扫描一行。因此,当使用前缀索引,定义好长度,就可以做到既节省空间,又不用额外增加太多的查询成本。
那么,你大概就会好奇了,前缀的长度如何确定呢?
在建立索引时,我们需要关注字段的区分度,区分度越高,重复的键值越少。
可以使用下面语句计算列上有多少不同的值:
select count(distinct email) as L from SUser;
然后,可以依次选取不同前缀长度来看:
mysql> select
count(distinct left(email,4))as L4,
count(distinct left(email,5))as L5,
count(distinct left(email,6))as L6,
count(distinct left(email,7))as L7,
from SUser;
前缀损失一般会损失区分度,因此在选取长度时心里需要对可以接受的损失比做一个预估,比如想要控制在5%之内,那么L4-L7里需要选取$\ge$95% L的值。
前缀索引对覆盖索引的影响
前缀索引除了可能增加扫描行数,还有其他影响。比如下面这两个语句:
select id,email from SUser where email='zhangssxyz@xxx.com';
如果使用index1(整个字符串的索引结构),可以利用覆盖索引,在index1查到结果就直接返回,不需要回表;而如果使用前缀索引,就必须回表,即使使用整个字符串的长度email(18),依然需要回表,因为系统不确定前缀索引的定义是否截断了完整信息。
在该例子中,使用前缀索引就用不上覆盖索引对查询性能的优化了,这也是在选择是否使用前缀索引时需要考虑的一个因素。
其他方式
对于邮箱这样的字段,由于用户名差异较大,使用前缀索引的效果可能不错。但有些字段前缀区分度不好,比如身份证号,这时候如果使用前缀索引,可能需要创建长度较长的前缀索引,才能满足区分度要求。但是这也意味着索引占用磁盘空间越大,搜索效率会越低。
假如,能够确定业务需求里只有按照身份证进行等值查询的需求,那么有更好的处理方式,既可以占用更小空间,又能达到相同查询效率:
(1)使用倒序存储
将身份证号倒过来存储,那么可能取6位就有足够的区分度。每次查询时,使用下面的方式:
select field_list from t where id_card = reverse('input_id_card_string');
(2)使用hash字段
可以在表上再创建一个整数字段,比如每次插入新纪录时用crc32()函数得到一个校验码字段。由于校验码可能冲突,在查询时候需要判断id_card字段是否相同。
来看上面两种方法的异同:相同点是都不支持范围查询,不同点有:
占用额外空间不同。倒序存储不消耗额外存储空间,而Hash字段需要增加一个字段。
CPU消耗不同。倒序存储方式每次读写都需要额外调用一次reverse函数,而Hash方式需要额外调用一次
crc32()函数,从两个函数的计算复杂度看的话前者更小。查询效率不同。使用Hash方式的查询性能相对更稳定,因为
crc32()冲突概率小,可以认为每次查询的平均扫描行数接近1,而倒序存储方式毕竟还是使用前缀索引方式,会增加扫描行数。
MySQL 11 怎么给字符串字段加索引?的更多相关文章
- MySQL 笔记整理(11) --怎么给字符串字段加索引?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 11) --怎么给字符串字段加索引? 日常工作中的登录系统,你很可能会使 ...
- MySQL:字符串字段加索引
1. 使用方式 1.1 全字段加索引 给整个字段加索引,索引存储整个字段的值. 数据量较小时,查询成本高,准确度高: 数据量较大时,比较耗费空间: 1.2 前缀索引 MySQL支持前缀索引,可以定义字 ...
- MySQL学习(一)日志与索引 --- 2019年1月
1.MySQL的架构 1).连接器 先根据Ip和端口号,用户名和密码,连接MySQL数据库,连接后如果没有下一步动作,连接就处于空闲状态,此时有一个连接超时时间的设置 wait_timeout默认8小 ...
- MySQL中大数据表增加字段,增加索引实现
MySQL中大数据表增加字段,通过增加索引实现 普通的添加字段sql ALTER TABLE `table_name` ADD COLUMN `num` int(10) NOT NULL DEFAUL ...
- MySQL性能优化 - 别再只会说加索引了
MySQL性能优化 MySQL性能优化我们可以从以下四个维度考虑:硬件升级.系统配置.表结构设计.SQL语句和索引. 从成本上来说:硬件升级>系统配置>表结构设计>SQL语句及索引, ...
- mysql中一半会选择什么样的字段为索引?(含索引创建删除查看公式)
一.数据量庞大的数据做索引 二.该字段经常出现在where的后面,以条件形式存在,经常被用户搜索的字段 三.很少被增删改的字段,因为增删改后,索引会重新排序 索引的创建 create index 索引 ...
- 字符串可以这样加索引,你知吗?《死磕MySQL系列 七》
系列文章 三.MySQL强人"锁"难<死磕MySQL系列 三> 四.S 锁与 X 锁的爱恨情仇<死磕MySQL系列 四> 五.如何选择普通索引和唯一索引&l ...
- Mysql性能优化:如何给字符串加索引?
导读 现代大部分的登录系统都支持邮箱.手机号码登录两种方式,那么如何在邮箱或者手机号码这个字符串上建立索引才能保证性能最佳呢? 今天这篇文章就来探讨一下在Mysql中如何给一个字符串加索引才能达到性能 ...
- 总结: MySQL(基础,字段约束,索引,外键,存储过程,事务)操作语法
1. 显示数据库列表 show databases; # 查看当前所有数据库 show databases \G #以行的方式显示 2. 在命令行中,执行sql语句 mysql -e 'show ...
- 为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》
群里一个小伙伴在问为什么MySQL字符串不加单引号会导致索引失效,这个问题估计很多人都知道答案.没错,是因为MySQL内部进行了隐式转换. 本期文章就聊聊什么是隐式转换,为什么会发生隐式转换. 系列文 ...
随机推荐
- Redis 集群实现分布式缓存的示例操作流程【Redis 系列之五】
〇.前言 Redis 集群的核心优势在于高可用性.可扩展性和高性能,特别适合需要处理大规模数据和高并发请求的应用场景. 本文先介绍了什么是 Redis 集群,然后通过示例,以手动和自动两种方式搭建集群 ...
- (原创)[开源][.Net Framework 4.0] SimpleLiveDataFeed(极易使用的采集数据滚动显示,基于MSChart)更新 v1.0,增加NuGet包
一.前言 不管还有没有用的,即然是自己原创,就开源了发出来吧,也算是在这互联网上留下了些许记忆. 碎碎念:很早之前的 Windows Mobile 6.5/6.5.3 相关开发记录因为懒惰,现在想回忆 ...
- require、include、require_once和use的区别/命名空间的使用方法
1.require.include require.include都是文件包含,不同的是require语句会输出错误信息,并且立即终止脚本处理.而include语句在没有找到文件时则会输出警告,不会终 ...
- 四大国产AI编程助手横向浅评
随着过去两个月里腾讯和字节先后官宣旗下的AI智能开发工具上线,加上去年10月份百度.阿里前后脚发布AI编程助手正式版,目前国内四大头部互联网公司--百度.阿里.腾讯.字节--旗下的AI编程助手们已悉数 ...
- df -h命令卡住 怎么办
df -h命令卡住 命令行输入df -h却发现一直卡在那里,有可能是挂载出了问题. 这种问题,大概率是由于 mount 的目录被删除了,但是没有提前执行 umount 操作,因此报错! 解决方法: 1 ...
- CatBoost算法原理及Python实现
一.概述 CatBoost 是在传统GBDT基础上改进和优化的一种算法,由俄罗斯 Yandex 公司开发,于2017 年开源,在处理类别型特征和防止过拟合方面有独特优势. 在实际数据中,存在大 ...
- 时间工具类之“LocalDateTime方案转换地域性时差问题->本地时间 转 UTC时间
一.使用方法 1.这里有使用LocalDateTime,Date, 2.直接使用LocalDateTime来将输入时间转为UTC还是没有摸索到,看了下源码发现根据偏移量去处理的,但是没有测试成功所以换 ...
- vue3 基础-生命周期函数
在 vue 中, 生命周期函数可理解为 "在某个时刻, 会自动执行的函数". 先直观感受一下图示. 一共就八个: <!DOCTYPE html> <html la ...
- JavaScript 从零实现物理模拟
@charset "UTF-8"; .markdown-body { line-height: 1.75; font-weight: 400; font-size: 15px; o ...
- 私有资产测绘&安全流水线Shovel
私有资产测绘&安全流水线Shovel(Preview)发布 发布版本:Shovel-v0.1.7 当前项目发布版本 Shovel-v0.1.7(预览版) | 企业级资产测绘管理,开启资配漏补新 ...