侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

MySQL字符串索引更合理的创建规则讨论

数据库  /  管理员 发布于 6年前   191

前言

针对使用MySQL的索引,我们之前介绍过索引的最左前缀规则,索引覆盖,唯一索引和普通索引的使用以及优化器选择索引等概念,今天我们讨论下如何更合理的给字符串创建索引。

如何更好的创建字符串索引

我们知道,MySQL中,数据和索引都是在一颗 B+树 上,我们建立索引的时候,这棵树所占用的空间越小,检索速度就会越快,而varchar格式的字符串有些会很长,那么在效率为上的今天,我们如何更加合理的建立字符串的索引呢?
假如说我们一张表中存在 email 字段,现在要给 email 字段创建索引,email 字段值的格式为:[email protected]。

有2种建立索引的方式:

1、直接给 email 字段建立索引:alter table t add index index1(email);

索引树结构为:

2、建立 email 的前缀索引:alter table t add index index2(email(6));

索引数据结构为:

此时我们的查询语句为:select id,name,email from t where email='[email protected]';

当使用index1索引时其执行步骤为:

1、从index1索引树查找索引值为[email protected]的主键值ID1;

2、根据ID1回表查到该行数据确实为[email protected],将结果加入结果集;

3、继续查找index1索引树下一个索引值是否满足[email protected],不满足则结束查询。

当使用index2索引时其执行步骤为:

1、从index2索引树查找索引值为zhangs的主键值ID1;

2、根据ID1回表查到该行数据确实为[email protected],将结果加入结果集;

3、 继续查找index2索引树下一个索引值是否满足zhangs,满足则继续回表查询该行数据是否为[email protected],不是则跳过继续查找;

4、持续查找index2索引树,直到索引值不是zhangs为止。

从以上分析中我们可以看出,全字段索引相比前缀索引来说,减少了回表的次数,但是如果我们将前缀从6个增加到7个8个的话,前缀索引回表的次数就会减少,也就是说,只要定义好前缀的长度,我们就能既节省空间又保证效率。

那么问题来了,我们怎么衡量使用前缀索引的长度呢?

1、使用 select count(distinct email) as L from t; 查询字段不同值的个数;

2、依次选取不同的前缀长度查看不同值的个数:

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 t;

然后根据实际可接受的损失比例,选取适合的最短的前缀长度。

前缀的长度问题我们解决了,但是一个问题是,如果使用前缀索引,那我们索引覆盖的特性就用不到了。
用全字段索引时,当我们查询select id,email from t where email='[email protected]';时,不用回表直接就能查到id和email字段。

但是用前缀索引时,MySQL并不清楚前缀是否会整个覆盖email的值,无论是否全包含都会根据主键值回表查询判断。

所以说,使用前缀索引虽然能节省空间保证效率但是却不能用到覆盖索引的特性,是否使用就在于具体考虑了。

其他字符串索引创建方式

实际情况实际考虑,并不是所有的字符串都能使用前缀截取的方式创建索引,如身份证号或者ip这些字符串使用前缀索引就不合理了,身份证号一般同一个地区的人前几位都是一模一样的,使用前缀索引就不合理了,而ip值我们一般在实际中将其转化为数字去存储。

针对身份证号,我们可以使用倒叙存储,取前缀创建索引或者使用crc32()函数来获取一个hash校验码(int值)当做索引。

倒叙:select field_list from t where id_card = reverse('input_id_card_string');

crc32:select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string'

这两种方式相对来说效率都差不多,都不支持范围查找,支持等值查找。

在倒叙方式中,需要使用reverse函数,但是回表次数可能比hash方式多。

在hash方式中,需要新建一个索引字段并调用crc32()函数。(注意:crc32()函数获取的结果不保证能唯一,可能存在重复的情况,但是这种情况概率较小),回表次数少,几乎1次就行。

最后

针对字符串索引,一般有以下几种创建方式:

1、字符串较短,直接全字段索引

2、字符串较长,且前缀区分度较好,创建前缀索引

3、字符串较长,前缀区分度不好,倒叙或hash方式创建索引(这种方式范围查询就不行了)

4、根据实际情况,遇到特殊字符串,特殊对待,如ip。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。


  • 上一条:
    mysql 定时任务的实现与使用方法示例
    下一条:
    MySQL控制用户输错密码尝试次数
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • Laravel 11.15版本发布 - Eloquent Builder中添加的泛型(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客