导读

  • 现代大部分的登录系统都支持邮箱、手机号码登录两种方式,那么如何在邮箱或者手机号码这个字符串上建立索引才能保证性能最佳呢?

  • 今天这篇文章就来探讨一下在Mysql中如何给一个字符串加索引才能达到性能最佳。

  • 本文首发于作者的微信公众号【码猿技术专栏】,原创不易,喜欢的朋友支持一下,谢谢!!!
  • 陈某将会从什么是前缀索引前缀索引和普通索引的比较如何建丽最佳性能的前缀索引前缀索引对覆盖索引的影响这几段来讲。

前缀索引

  • 顾名思义,对于列值较长,比如BLOBTEXTVARCHAR,就 "必须" 使用前缀索引,即将值的前一部分作为索引。因为索引的存储也是需要空间的,同样索引太长维护起来也比较困难。

  • 比如我们给User表中的邮箱添加前缀索引,如下:

   alter table user add index index1(email(7));
  • 上述语句将email的前7个字符作为索引。

前缀索引和普通索引比较

  • 我们分别将email的全部作为索引和前7个字符作为索引来看看在性能上有什么差异。建立索引的语句如下:

  alter table user add index index1(email);

  alter table user add index index2(email(7));
  • 假设有user表中有这样几条数据(id,name,email):(1,"陈某","chenmou1993@xxx")(2,"张某","chenmou1994@xxx")(3,"李某","chenmou1995@xxx")(4,"王某","chenmou1996@xxx")

  • 对应于index1和index2的索引树如下两张图:

  • 如果执行下面的查询语句,Mysql如何利用索引来查询呢?

  select * from user where email="chenmou1995@xxx";

【1】普通索引的执行过程

  1. 从index1索引树找到满足索引值是chenmou1995@xxx的这条记录,取得id=2的值;

  2. 到主键上查到主键值是id=2的行,判断email的值是正确的,将这行记录加入结果集;

  3. index1索引树上刚刚查到的位置的下一条记录,发现已经不满足email=chenmou1995@xxx的条件了,循环结束。

这个过程中,只需要回主键索引取一次数据,所以系统认为只扫描了一行

【2】前缀索引的执行过程

  1. 从index2索引树找到满足索引值是chenmou的记录,找到的第一个是id=1;

  2. 到主键上查到主键值是id=1的行,判断出email的值不是chenmou1995@xxx,这行记录丢弃;

  3. 取index2上刚刚查到的位置的下一条记录,发现仍然是chenmou,取出id=2,再到ID索引上取整行然后判断,这次值对了,将这行记录加入结果集;

  4. 重复上一步,直到在idxe2上取到的值不是chenmou时,循环结束。

  在这个过程中,要回主键索引取4次数据,也就是扫描了4行。

  • 通过以上查询的对比,很容易就可以发现,使用前缀索引后,可能会导致查询语句读数据的次数变多。

  • 但是对于这个查询语句来说,如果建立的前缀索引的长度为13呢?那么满足chenmou1995的记录只有一个,这样就可以直接定位到id=2,此时不但空间缩小了,扫描的行数也减少了。

  • 于是结论就来了:使用前缀索引,只要定义好长度,就可以做到既节省空间,又不用额外增加太多的查询成本。

  • 那么如何建立正确的前缀索引才能达到最佳的性能呢?接着往下看................

如何建立最佳性能的前缀索引

  • 通过上述的比较,可以得出一个结论,建立前缀索引的区分度越高越好,意味着重复的键值越少

  • 那么如何统计区分度,其实很简单,只需要判断数据库中重复的次数即可。sql如下:

  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 user;
  • 但是如果对于使用前缀区分度不太好的情况,比如,我们国家的身份证号,一共18位,其中前6位是地址码,所以同一个县的人的身份证号前6位一般会是相同的。 这时候如果对身份证号做长度为6的前缀索引的话,这个索引的区分度就非常低了。

  • 按照我们前面说的方法,可能你需要创建长度为12以上的前缀索引,才能够满足区分度要求。

  • 但是,索引选取的越长,占用的磁盘空间就越大,相同的数据页能放下的索引值就越少,搜索的效率也就会越低。

  • 那么,如果我们能够确定业务需求里面只有按照身份证进行等值查询的需求,还有没有别的处理方法呢?这种方法,既可以占用更小的空间,也能达到相同的查询效率。现在简单的介绍一种解决此种问题的方式,当然方法肯定不止一种,如下:

  倒序存储

  如果你存储身份证号的时候把它倒过来存,每次查询的时候,你可以这么写:

   select field_list from t where id_card = reverse('输入的身份证号');

  由于身份证号的最后6位没有地址码这样的重复逻辑,所以最后这6位很可能就提供了足够的区分度。当然了,实践中你不要忘记使用count(distinct)方法去做个验证。

前缀索引对覆盖索引的影响

  • 前缀索引会导致覆盖索引失效,查询语句如下:

  select id,name from user where email="chenmou1995@xxx";
  • 由于使用了前缀索引,因此必须会回表验证查询到的时候正确,此处使用了覆盖索引也是无效的。

  • 也就是说,使用前缀索引就用不上覆盖索引对查询性能的优化了,这也是你在选择是否使用前缀索引时需要考虑的一个因素。

总结

  • 如何给字符串加索引是一个需要考量的问题,陈某在这里给出如下的建议:

  1. 如果字符串长度很短,建议直接用全部作为索引。

  2. 使用前缀索引注意分析区分度,区分度越高越好。

  3. 使用前缀索引需要考虑覆盖索引失效的问题。

Mysql性能优化:如何给字符串加索引?的更多相关文章

  1. Mysql 性能优化6【重要】 索引优化

    b tree索引 myisam 是通过物理位置来查找引用行的 innodb 是通过主键来查找引用行的 索引优化策略 b-tree索引对数据长度有限制,所以text等比较长的列可以建立前缀索引 btre ...

  2. MySQL性能优化 - 别再只会说加索引了

    MySQL性能优化 MySQL性能优化我们可以从以下四个维度考虑:硬件升级.系统配置.表结构设计.SQL语句和索引. 从成本上来说:硬件升级>系统配置>表结构设计>SQL语句及索引, ...

  3. mysql性能优化-慢查询分析、优化索引和配置 (慢查询日志,explain,profile)

    mysql性能优化-慢查询分析.优化索引和配置 (慢查询日志,explain,profile) 一.优化概述 二.查询与索引优化分析 1性能瓶颈定位 Show命令 慢查询日志 explain分析查询 ...

  4. [MySQL性能优化系列]巧用索引

    1. 普通青年的索引使用方式 假设我们有一个用户表 tb_user,内容如下: name age sex jack 22 男 rose 21 女 tom 20 男 ... ... ... 执行SQL语 ...

  5. MySQL性能优化:索引

    MySQL性能优化:索引 索引提供指向存储在表的指定列中的数据值的指针,然后根据您指定的排序顺序对这些指针排序.数据库使用索引以找到特定值,然后顺指针找到包含该值的行.这样可以使对应于表的SQL语句执 ...

  6. MySQL性能优化(三):索引

    原文:MySQL性能优化(三):索引 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/vbi ...

  7. MYSQL性能优化的最佳20+条经验

    MYSQL性能优化的最佳20+条经验 2009年11月27日 陈皓 评论 148 条评论  131,702 人阅读 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数 ...

  8. 二十种实战调优MySQL性能优化的经验

    二十种实战调优MySQL性能优化的经验 发布时间:2012 年 2 月 15 日 发布者: OurMySQL 来源:web大本营   才被阅读:3,354 次    消灭0评论     本文将为大家介 ...

  9. MySQL性能优化的21个最佳实践

    http://www.searchdatabase.com.cn/showcontent_38045.htm MySQL性能优化的21个最佳实践 1. 为查询缓存优化你的查询 大多数的MySQL服务器 ...

随机推荐

  1. python爬虫之selenium+打码平台识别验证码

    1.常用的打码平台:超级鹰.打码兔等 2.打码平台在识别图形验证码和点触验证码上比较好用 (1)12306点触验证码 from selenium import webdriver from selen ...

  2. yii2设置默认控制器

    以Yii2高级模板配置为例

  3. YAML语法使用,JSR303数据校验

    YAML YAML是 "YAML Ain't a Markup Language" (YAML不是一种置标语言)的递归缩写 # yaml配置 server: prot: YAML语 ...

  4. Golang 使用Protocol Buffer 案例

    目录 1. 前言 2. Protobuf 简介 2.1 Protobuf 优点 2.2 Protobuf 缺点 2.3 Protobuf Golang 安装使用 3. Protobuf 通讯案例 3. ...

  5. vue中的自定义分页插件组件

    介绍一下,已经有很多的vue分页的组件了,大家都是大同小易,那么我就结合自身的使用,写出了一片文章 首先在新建一个分页模块 在模块中引入相应的代码,(内有详细的注释) template中 <di ...

  6. 2017、2018面试分享(js面试题记录)记得点赞分享哦;让更多的人看到~~

    2017面试分享(js面试题记录) 1. 最简单的一道题 '11' * 2 'a8' * 3 var a = 2, b = 3; var c = a+++b; // c = 5 2. 一道this的问 ...

  7. Nginx server name配置子域名二级域名

    绑定子域名到不同目录(子站) 网站的目录结构为 /var/www/html: ├── fx └── blog└── photo html为nginx的默认网站目录. sudo vi /etc/ngin ...

  8. step(iter)、epoch、batch size之间的关系

    转自:https://blog.csdn.net/wcy23580/article/details/90082221

  9. url,href和src的区别,defer和async的区别

    URL(Uniform Resource Locator):统一资源定位符,互联网上的每个文件都有一个唯一的URL,基本URL包含协议,IP地址,路径和文件名. 重点:herf和src的区别 href ...

  10. JavaScript入门进阶(二)

    JavaScript进阶入门(二) 转换为数字 使用parseInt() parseInt函数会先查看位置0处的字符,如果该位置不是有效数字,则将返回NaN,如果0处的字符是数字,则将查看位置1处的字 ...