暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

MySQL系列7 - 结合案例分析如何使用索引

栋总侃技术 2021-03-18
1512

案例一:有一张user表包含身份证号这一字段,且需要根据身份证号码建立索引。

解决方案1: 正常建立身份证号索引

该方案确实有效,根据身份证号可以比较快的查询出该行用户的信息。


此时,我们分析一下,身份证号码是18位,索引字符串比较长,占用的磁盘空间自然也比较大,带来的搜索效率随着也会降低。而且身份证号,前6位是地址标识,其实区分度并不高。


例如我们要查询某个身份证号为 420103xxxxxxxxxxxx的用户,会从第一条以420103开头的的索引逐个匹配。


优化方案1:我们把字符串倒着存,在根据身份证号获取用户行数据时,

    select * from user where card_id = reverse('420103xxxxxxxxxxxx');

    虽然身份证号的反转后的字符串出现重复开头的概率也存在,但是比正向字符串出现重复的概率会小得多。


    优化方案2: 我们新增一个字段就用来存储身份证号码的后六位,并作为索引,在根据身份证号获取用户行数据时,

      select * from user where card_id_cc = 'xxxxxx' and card_id = '420103xxxxxxxxxxxx';


      我们再来对以上优化做出总结:

      1. 两种优化方式的目标都是增加索引字符串的区分度。一个通过反转实现、一个通过减少索引字符串的长度实现。

      2. 优化后的方案是不支持范围查询的,这里身份证号码应该是没有范围查询的需求的。如果是其他的字段,需要考虑当前或者未来的场景是否需要范围查询,酌情使用。


      我们再从业务角度出发,当前这张user表的业务场景是怎样的?如果仅仅是某个学校的学生,假设这个学校每年新增2000位学生,50年才有10万条记录,那还有必要这样优化吗?如果分别是区政府、市政府、省政府使用该系统结合着分析数据量以及身份证号前六位标识的规则,是否还有其他的优化方案?以上的优化点只是用来抛砖引玉,大家结合实际业务中灵活发挥。


      案例二:仍然是案例一的表,再看下这条语句:

        select * from user where card_id = 420103xxxxxxxxxxxx;

        card_id明明是索引,为啥这条语句这么慢,而且explain一下,怎么全表扫描了。


        分析:这是因为 card_id是 varchar(32)类型,而输入的参数却是整型,需要做类型转换。在进行类型转换时会破坏索引的有序性,因此优化器决定不走索引了。


        扩展:还有一种情形也需要注意,在两张表做联合查询时,虽然看着是同一个字段,可能两张表的字符集不一样(一个是utf8mb4,另一个是utf8)。这种情况也不会命中索引。


        解决方案1: 修改其中一张表的字符集

          alter table user modify card_id varchar(32) CHARACTER SET utf8mb4 default null;


          解决方案2: 由于表的数据量都比较大,修改字符集代价过高,直接在sql中显示调用函数

            select user.* from user , table2  where user.card_id = CONVERT(table2.card_id USING utf8);


            以上提到的优化点重点在于提升各位解决问题的视野,大家可以从技术的层面、业务的层面,同时还可以使用一些巧方法来优化对MySQL的使用。下一章我会结合我个人工作中遇到的实际场景来分析如何一步步做优化的。


            往期回顾:

            MySQL系列1 - sql语句的执行过程以及redo log和binlog扮演的角色

            MySQL系列2 - 什么是索引以及优化器怎么工作的?

            MySQL系列3 - 全局锁、表锁、行锁

            MySQL系列4 - 你了解 order by 的工作原理吗?

            MySQL系列5 - 一文讲透 join语句

            MySQL系列6 - join语句的优化



            文章转载自栋总侃技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论