Mysql性能优化:如何给字符串加索引?

简介:

Mysql性能优化:如何给字符串加索引?
导读
现代大部分的登录系统都支持邮箱、手机号码登录两种方式,那么如何在邮箱或者手机号码这个字符串上建立索引才能保证性能最佳呢?
今天这篇文章就来探讨一下在Mysql中如何给一个字符串加索引才能达到性能最佳。
本文首发于作者的微信公众号【码猿技术专栏】,原创不易,喜欢的朋友支持一下,谢谢!!!
陈某将会从什么是前缀索引、前缀索引和普通索引的比较、如何建丽最佳性能的前缀索引、前缀索引对覆盖索引的影响这几段来讲。

前缀索引
顾名思义,对于列值较长,比如BLOB、TEXT、VARCHAR,就 "必须" 使用前缀索引,即将值的前一部分作为索引。因为索引的存储也是需要空间的,同样索引太长维护起来也比较困难。
比如我们给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】普通索引的执行过程

从index1索引树找到满足索引值是chenmou1995@xxx的这条记录,取得id=2的值;
到主键上查到主键值是id=2的行,判断email的值是正确的,将这行记录加入结果集;
取index1索引树上刚刚查到的位置的下一条记录,发现已经不满足email=chenmou1995@xxx的条件了,循环结束。
这个过程中,只需要回主键索引取一次数据,所以系统认为只扫描了一行。

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

从index2索引树找到满足索引值是chenmou的记录,找到的第一个是id=1;
到主键上查到主键值是id=1的行,判断出email的值不是chenmou1995@xxx,这行记录丢弃;
取index2上刚刚查到的位置的下一条记录,发现仍然是chenmou,取出id=2,再到ID索引上取整行然后判断,这次值对了,将这行记录加入结果集;
重复上一步,直到在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";
由于使用了前缀索引,因此必须会回表验证查询到的时候正确,此处使用了覆盖索引也是无效的。
也就是说,使用前缀索引就用不上覆盖索引对查询性能的优化了,这也是你在选择是否使用前缀索引时需要考虑的一个因素。

总结
如何给字符串加索引是一个需要考量的问题,陈某在这里给出如下的建议:
如果字符串长度很短,建议直接用全部作为索引。
使用前缀索引注意分析区分度,区分度越高越好。
使用前缀索引需要考虑覆盖索引失效的问题。

如果觉得作者写的好,有所收获的话,点个关注,推荐一波,文章首发于公众号!!!
原文地址https://www.cnblogs.com/Chenjiabing/p/12620427.html

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
存储 SQL 关系型数据库
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
mysql底层原理:索引、慢查询、 sql优化、事务、隔离级别、MVCC、redolog、undolog(图解+秒懂+史上最全)
|
存储 关系型数据库 MySQL
MySQL数据库索引的数据结构?
MySQL中默认使用B+tree索引,它是一种多路平衡搜索树,具有树高较低、检索速度快的特点。所有数据存储在叶子节点,非叶子节点仅作索引,且叶子节点形成双向链表,便于区间查询。
327 4
|
存储 关系型数据库 MySQL
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
阿里面试:MySQL 一个表最多 加几个索引? 6个?64个?还是多少?
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
357 2
|
存储 关系型数据库 MySQL
MySQL覆盖索引解释
总之,覆盖索引就像是图书馆中那些使得搜索变得极为迅速和简单的工具,一旦正确使用,就会让你的数据库查询飞快而轻便。让数据检索就像是读者在图书目录中以最快速度找到所需信息一样简便。这样的效率和速度,让覆盖索引成为数据库优化师傅们手中的尚方宝剑,既能够提升性能,又能够保持系统的整洁高效。
434 9
|
机器学习/深度学习 关系型数据库 MySQL
对比MySQL全文索引与常规索引的互异性
现在,你或许明白了这两种索引的差异,但任何技术决策都不应仅仅基于理论之上。你可以创建你的数据库实验环境,尝试不同类型的索引,看看它们如何影响性能,感受它们真实的力量。只有这样,你才能熟悉它们,掌握什么时候使用全文索引,什么时候使用常规索引,以适应复杂多变的业务需求。
401 12
|
存储 SQL 关系型数据库
MySQL 核心知识与性能优化全解析
我整理的这份内容涵盖了 MySQL 诸多核心知识。包括查询语句的书写与执行顺序,多表查询的连接方式及内、外连接的区别。还讲了 CHAR 和 VARCHAR 的差异,索引的类型、底层结构、聚簇与非聚簇之分,以及回表查询、覆盖索引、左前缀原则和索引失效情形,还有建索引的取舍。对比了 MyISAM 和 InnoDB 存储引擎的不同,提及性能优化的多方面方法,以及超大分页处理、慢查询定位与分析等,最后提到了锁和分库分表可参考相关资料。
285 0
|
关系型数据库 MySQL
MySQL字符串拼接方法全解析
本文介绍了四种常用的字符串处理函数及其用法。方法一:CONCAT,用于基础拼接,参数含NULL时返回NULL;方法二:CONCAT_WS,带分隔符拼接,自动忽略NULL值;方法三:GROUP_CONCAT,适用于分组拼接,支持去重、排序和自定义分隔符;方法四:算术运算符拼接,仅适用于数值类型,字符串会尝试转为数值处理。通过示例展示了各函数的特点与应用场景。
|
12月前
|
缓存 关系型数据库 BI
使用MYSQL Report分析数据库性能(下)
使用MYSQL Report分析数据库性能
664 158
|
关系型数据库 MySQL 数据库
自建数据库如何迁移至RDS MySQL实例
数据库迁移是一项复杂且耗时的工程,需考虑数据安全、完整性及业务中断影响。使用阿里云数据传输服务DTS,可快速、平滑完成迁移任务,将应用停机时间降至分钟级。您还可通过全量备份自建数据库并恢复至RDS MySQL实例,实现间接迁移上云。

推荐镜像

更多