字符串可以这样加索引,你知吗?《死磕MySQL系列 七》
系列文章
六、五分钟,让你明白MySQL是怎么选择索引《死磕MySQL系列 六》
相信大多数小伙伴跟咔咔一样,给字符串添加索引从未设置过长度,今天就来聊聊如何正确的给字符串加索引。
一、如何建立索引
大多数系统都会存在用户表,并且系统初始设计使用了手机号码登录的。
这是产品提出了一个需求,让系统也可以支持邮箱登录。
肯定知道的是若不给邮箱字段添加索引执行查询是会全表扫描。
此时你心里窃喜这还不简单,给邮箱字段加个索引完事呗!但要做到复杂的需求做好,简单的需求要最好,减轻一切对系统的压力。
此时的你拿起键盘就执行了alter table table_name add index idx_field (field)
有部分小伙伴不喜欢命令行创建索引,喜欢使用phpmyadmin工具来操作MySQL,那么在建立索引时有没有发现后边可以设置大小呢?
通过上边给大家展示的图片知道字符串建立索引是可以定义长度的,那么两者有什么区别。
使用命令行alter table table_name add index idx_field (field)
直接创建的索引默认是包含整个字符串。
若这样执行就指定了索引前缀长度alter table table_name add index idx_field (field(6))
一图解千愁,看一下建立的两个索引结构是什么样的。
索引一结构图
索引二结构图
从图中可以看到,指定了索引长度为6那么就只取邮箱字段的前6个字段,相对索引包含整个字符串来说每个节点存储的数据会更多。
索引那篇文章也给大家说了建立索引在合适的范围内越小越好。
万物皆两面,有坏就有好,第六期文章误选索引的因素之一就是扫描行数。
索引长度减少带来的影响就是索引基数变大,从而增加额外的扫描记录数(执行explain的row字段)。
此时要执行select id,name,email from mac_user where email='1397393964@qq.com';
给整个字符串添加索引执行流程
1、从email索引树找到满足1397393964@qq.com的记录,得到主键ID为1
2、根据ID为1到主键索引树找到这条记录并判断email是否正确,将这行记录假如结果集。
3、重复第一步,直到不满足查询条件,循环结束。
指定索引长度执行流程
1、从email索引树找到满足139739的记录,得到主键ID为1
2、根据ID为1到主键索引树找到这条记录并判断email不正确,丢弃这行记录。
3、在email索引树找刚刚查询的下一条记录,发现还是139739,去除ID2,再到ID的索引树进行判断,当值对后加入结果集。
4、再继续重复上一步,直到不满足查询条件,循环结束。
结论
在模拟执行流程过程中很容易就发现,使用前缀索引会导致读取数据的次数增加,那是不是就代表使用前缀索引会增加查询代价呢?
肯定不是的,试想此时定义的长度是6那么设置为7或者8呢!是不是会好很多,图中的案例为了方便设置了三个一样的数据,但实际情况基本不会出现这样的情况。
建立索引关注的是区分度,只有区分度越高,重复值就越少,查询效率就越高。
所以使用前缀索引,只要定义好长度,就可以坐到既节省空间,又不用额外增加太多的查询代价。
二、创建索引如何确定使用多长的前缀
MySQL中关键词distinct
可以返回本列不同的结果集。
例如查询email列有多少个不同的值select count(distinct email) as num from mac_user。
如何计算列不同前缀有多少行
结合MySQL自带的函数left来实现,例如select count(distinct left (email,4)) as num4 from mac_user
,截取email的前四个字符串计算有多少行。
再用这个值去除总数得到的就是比例,根据业务情况来判断多少比例可以。
三、使用前缀索引的影响
使用前缀索引会增加扫描行数,同时也会使覆盖索引失效。
为什么会影响覆盖索引?
若执行语句为select id,email from mac_user where email = '1397393964@qq.com'
。
使用整个字符串索引结构查询可以使用覆盖索引,从email索引获取到结果就直接返回了,不用再进行回表。
若使用前缀索引在email索引获取到结果后还需要回到id索引在查一下判断查询的email的值是否正确。
哪怕是设置了大于了email的长度也会回表再进行判断,因为MySQL并不知道定义的前缀是否截取了完整信息。
结论
使用前缀索引会增加扫描行数,同样也使用不到覆盖索引。这个因素是你选择是否使用前缀索引要考虑的一个因素。
如果你不知道使用前缀索引还是全字符串索引,本地进行测试选一个合适的方案上到生产环境即可。
四、如何把不可以变为可以使用
假设身份认证系统存储的是身份证号,应该都知道身份证号前6位是地址码,同县的身份证号前6位一般是一样的。
这样使用前缀索引的话区分度会十分低,不但没有起到加速查询的作用,反而会造成索引区分度不大影响查询性能。
若把索引长度越长则每个节点存放的索引值就越少,查询效率也会变的低效。
如果解决这种场景
第一种方案
存储数据时将数据倒叙存储,查询时在正序处理一下即可
第二种方案
在表中新增一个字段,存储数据的hash值,给hash添加前缀索引。
区别
使用这两种方案共同点都不支持范围查询,都只能等值查询。
从占用空间来看:倒叙方式不会增加额外的存储空间,hash会增加一个字段。两者在空间不相上下
从CPU消耗来看:倒叙需要使用函数reverse,hash需要使用crc32 ,reverse消耗会小
从查询效率来看:hash查询更稳定,crc32计算的值虽有冲突但概率非常小,基本每次查询的平均扫描行数接近1。而倒叙使用的前缀索引方式,还会增加扫描行数。
五、总结
直接给字符串创建占用空间。
创建前缀索引,节省空间,会增加扫描行数,无法使用覆盖索引。
倒叙存储,创建前缀索引解决区分度不大的问题。
使用hash方式,查询稳定,不支持范围查询。
“
坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮助,我是咔咔,下期见。
”
字符串可以这样加索引,你知吗?《死磕MySQL系列 七》的更多相关文章
- 为什么MySQL字符串不加引号索引失效?《死磕MySQL系列 十一》
群里一个小伙伴在问为什么MySQL字符串不加单引号会导致索引失效,这个问题估计很多人都知道答案.没错,是因为MySQL内部进行了隐式转换. 本期文章就聊聊什么是隐式转换,为什么会发生隐式转换. 系列文 ...
- 如何选择普通索引和唯一索引《死磕MySQL系列 五》
系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...
- 五分钟,让你明白MySQL是怎么选择索引《死磕MySQL系列 六》
系列文章 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强人"锁"难<死磕MySQL系列 三> 四.S 锁与 X 锁的 ...
- mysql系列七、mysql索引优化、搜索引擎选择
一.建立适当的索引 说起提高数据库性能,索引是最物美价廉的东西了.不用加内存,不用改程序,不用调sql,只要执行个正确的'create index',查询速度就可能提高百倍千倍,这可真有诱惑力.可是天 ...
- MySQL 笔记整理(11) --怎么给字符串字段加索引?
笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> (本篇内图片均来自丁奇老师的讲解,如有侵权,请联系我删除) 11) --怎么给字符串字段加索引? 日常工作中的登录系统,你很可能会使 ...
- MySQL:字符串字段加索引
1. 使用方式 1.1 全字段加索引 给整个字段加索引,索引存储整个字段的值. 数据量较小时,查询成本高,准确度高: 数据量较大时,比较耗费空间: 1.2 前缀索引 MySQL支持前缀索引,可以定义字 ...
- Mysql性能优化:如何给字符串加索引?
导读 现代大部分的登录系统都支持邮箱.手机号码登录两种方式,那么如何在邮箱或者手机号码这个字符串上建立索引才能保证性能最佳呢? 今天这篇文章就来探讨一下在Mysql中如何给一个字符串加索引才能达到性能 ...
- 总结:如何使用redis缓存加索引处理数据库百万级并发
前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1000万条数据,可以参考我之前的文章插入数据, ...
- 使用redis缓存加索引处理数据库百万级并发
使用redis缓存加索引处理数据库百万级并发 前言:事先说明:在实际应用中这种做法设计需要各位读者自己设计,本文只提供一种思想.准备工作:安装后本地数redis服务器,使用mysql数据库,事先插入1 ...
随机推荐
- Jmeter系列(11)- 自动化压力测试逻辑思路及例子
为什么需要进行自动化压力测试 手动逐步加压,需要人工改变并发数,还要等待.所有,我们完全可以制定好策略,让程序自动加压,自动等待,输出报告 实现思路 Jmeter脚本(.jmx文件)- 压测逻辑 Sh ...
- 动图图解GC算法 - 让垃圾回收动起来!
原创:码农参上(微信公众号ID:CODER_SANJYOU),欢迎分享,转载请保留出处. 提到Java中的垃圾回收,我相信很多小伙伴和我一样,第一反应就是面试必问了,你要是没背过点GC算法.收集器什么 ...
- 实例:建立图书借阅系统的UML模型
1.需求分析 图书借阅系统的组成 2.具体的功能详细描述: (1)管理员登录系统,进入借书工作状态,等待借书处理. (2)读者找到所需图书,在借书处上刷卡机上刷卡. (3)管理员对借阅证进行资格审查. ...
- C语言练习:hackerrank十五关
第一关:Hello World C 输入一行字符串(可能含空格),输出hello world\n,字符串 Sample Input 0 Welcome to C programming. Sample ...
- 使用 WPF + Chrome 内核实现 在线客服系统 的复合客服端程序
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 免费使用 & 私有化部署免费下载:https://docs.sh ...
- ECMA 2022 (es13) 新特性
本文主要整理了截至到 2021年10月12日 为止的且处于 Stage 3->Stage 4 阶段的ECMA提案. 主要包括: Class Fields RegExp Match Indices ...
- 重磅 | 阿里开源首个 Serverless 开发者平台 Serverless Devs
Serverless 从概念提出到应用,已经走过了 8 个年头,开发者对 Serverless 的使用热情不断高涨.为帮助开发者实现一键体验多云产品,极速部署 Serverless 项目,10 月 2 ...
- wqs二分 学习笔记
wqs二分学习笔记 wqs二分适用题目及理论分析 wqs二分可以用来解决这类题目: 给你一个强制要求,例如必须\(n\)条白边,或者划分成\(n\)段之类的,然后让你求出最大(小)值.但是需要满足图像 ...
- 题解 [POI2013]SPA-Walk
题目传送门 题目大意 给出两个长度为 \(n\) 的 \(01\) 串,问是否可以通过某一位把 \(s\) 变为 \(t\),但是中途不能变为 \(k\) 个 \(01\) 串中任意一个,问是否可行. ...
- MySQL ENGINES 引擎
引擎 存储引擎是数据库底层软件组织. 数据库管理系统(DBMS)使用数据引擎进行创建.查询.更新和删除数据. 不同的存储引擎提供不同的存储机制.索引技巧.锁定水平等功能. MySQL的核心就是存储引擎 ...