我们都知道,当数据表中的数据日益增长后,查询会变得越来越慢,当初在表设计之初,尚未考虑创建索引的话,那么现在正是必要的时候。可是,如果对于MySQL使用索引的策略不了解,或是脱离了具体业务场景,那么,创建出来的索引,也发挥不了多大的作用。本文,就从我刚刚完成的一个项目入手,介绍如何正确的设计联合索引,以在实战项目中真正的发挥作用。

实际的业务场景

下图展示了项目所涉及的实际业务场景:

可以看到,查询条件主要涉及:视频分区、产品类别、产品、视频时长 和 发布时间。

其中,视频分区下,还有子分区:

产品下面,还有所属品牌:

所以,我们可以把查询条件做个梳理:1、视频分区 > 子分区,2、产品类别 > 产品 > 品牌。其中 产品类别产品 会根据用户选择的 视频分区子分区 的不同而变化,这样就会衍生出很多不同的业务逻辑 和 查询条件的组合:

  • 视频分区 > 子分区 > 产品类别 > 产品 > 品牌

这代表了用户既选了视频分区和子分区,同时又基于所属子分区下的产品类别,又选择了产品和品牌,即 所有关键的查询条件都用上了。下面的示意逻辑相同,只是组合不同而已。

  • 视频分区 > 子分区 > 产品类别
  • 视频分区 > 子分区 > 产品 > 品牌
  • 视频分区 > 产品类别 > 产品 > 品牌
  • 视频分区 > 产品类别
  • 视频分区 > 产品 > 品牌
  • 产品类别 > 产品 > 品牌
  • 产品 > 品牌

这里只列举了部分查询条件的组合,其实还有更多。其中特别标注出来的,是在实际使用场景下,常用的查询组合。下面我们就来看一看,如何基于这些查询条件,设计出合理的索引。

基于业务场景的联合索引的设计方案

我们把索引简单的分为 单列索引多列索引,多列索引被称为 联合索引复合索引,对于查询语句中的 where 条件,如果某些条件是这个查询中频繁用到的组合,那么,通常会创建联合索引,来提升查询效率。

但是,对于一个没有深谙其道的人来讲,他可能会这样设计联合索引:

  1. 给每个查询字段创建一个 单列索引

    CREATE INDEX 索引名称 ON 表名 (视频分区);
    CREATE INDEX 索引名称 ON 表名 (子分区);

    ...

  2. 只创建一个能覆盖到所有查询条件的 联合索引

    CREATE INDEX 索引名称 ON 表名 (视频分区, 子分区, 产品类别, 产品, 品牌);

以为这样,就可以让索引发挥全部作用,适用于所有查询条件的组合了。其实,联合索引 有一个最左匹配原则,从左至右匹配你的查询条件,直至断掉终止,如果索引列的第一个字段都尚不能匹配,则用不上此索引。比如:

  • 我们查询 视频分区 > 子分区 > 产品类别 > 产品 > 品牌 这些条件组合,当然可以用到上面创建的索引,因为查询条件与索引列完全对的上。
  • 如果查询 产品类别 > 产品 > 品牌 的话,则索引就无效了,因为索引列的第一个索引字段 视频分区 不在 where 查询条件中,最左匹配原则一开始就失败了,所以用不上索引。
  • 如果查询 视频分区 > 子分区,这是符合最左匹配原则的【英文叫 leftmost prefix of the index】,这个 leftmost 就告诉我们,虽然索引列并不完全匹配查询条件,但是部分匹配,而且必须顶着头的、排着队的、中间没有断掉的匹配了,即使尾巴断掉了没有关系,依然可以用上此索引。
  • 最后,如果查询 视频分区 > 子分区 + 发布时间 这组条件,能否用的上此索引呢?答案是肯定的,我不管你 where 条件中,哪些列不是索引列,我只关心你 where 条件中,哪些列在索引列之中,并且符合最左匹配就行了。

好了,到这里,我们应该逐渐清楚的认识到,仅仅创建一个包含所有查询条件的联合索引 视频分区, 子分区, 产品类别, 产品, 品牌 是远远不够的,而是需要根据业务需求和使用场景,将可能会频繁用到的查询条件,进行不同的排列组合,设计出一个折中的 联合索引 的方案。

正如你在本文前一部分看到的,在我列举出的部分查询条件中,着重标注出来的那些,就是我认为会最频繁使用到的组合,所以,需要相应的创建多个不同组合的 联合索引,以此来应对前端操作用户选择不同查询条件时,能够最大限度的命中索引,提升查询效率。

索引无法解决的问题

你应该也能看得出来,即使合理的创建了 联合索引,也无法覆盖到全部的查询条件的各种组合。好吧,就算你真的根据所有的组合,都相应的创建了 联合索引,但还有最后一关你过不去,那就是 模糊查询。你注意到,我的项目中,用到了根据用户输入的内容,来进行搜索,这必然需要使用模糊查询来实现,但是,%xxx% 这种形式的模糊查询,是无论如何也用不上索引的。

针对以上问题,我突发奇想,想到了一个绝妙的方案,并加以实施,应用到了我的项目中,结果效果非常好。在下一篇,我再作具体介绍。

MySQL联合索引的排列组合应用实战的更多相关文章

  1. 三道MySQL联合索引面试题,淘汰80%的面试者,你能答对几道

    众所周知MySQL联合索引遵循最左前缀匹配原则,在少数情况下也会不遵循(有兴趣,可以翻一下上篇文章). 创建联合索引的时候,建议优先把区分度高的字段放在第一列. 至于怎么统计区分度,可以按照下面这种方 ...

  2. MySQL 联合索引详解

    MySQL 联合索引详解   联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c ...

  3. mysql 联合索引(转)

    http://blog.csdn.net/lmh12506/article/details/8879916 mysql 联合索引详解 联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中 ...

  4. [转]mysql联合索引

    mysql联合索引   命名规则:表名_字段名1.需要加索引的字段,要在where条件中2.数据量少的字段不需要加索引3.如果where条件中是OR关系,加索引不起作用4.符合最左原则 https:/ ...

  5. SQL Server中的联合主键、聚集索引、非聚集索引、mysql 联合索引

    我们都知道在一个表中当需要2列以上才能确定记录的唯一性的时候,就需要用到联合主键,当建立联合主键以后,在查询数据的时候性能就会有很大的提升,不过并不是对联合主键的任何列单独查询的时候性能都会提升,但我 ...

  6. MySQL联合索引VS单列索引

    MySQL联合索引VS单列索引 以一个一千万数据量的表格为例 1. 建表建索引 USE foo; DROP TABLE IF EXISTS tmp; CREATE TABLE tmp ( id INT ...

  7. MySQL联合索引最左匹配范例

    MySQL联合索引最左匹配范例 参考文章:http://blog.jobbole.com/24006/ 创建示例表. 示例表来自MySQL官方文档: https://dev.mysql.com/doc ...

  8. 我说MySQL联合索引遵循最左前缀匹配原则,面试官让我回去等通知

    面试官: 我看你的简历上写着精通MySQL,问你个简单的问题,MySQL联合索引有什么特性? 心想,这还不简单,这不是问到我手心里了吗? 听我给你背一遍八股文! 我: MySQL联合索引遵循最左前缀匹 ...

  9. mysql联合索引详解

    联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索 引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b ...

随机推荐

  1. spring提供的可拓展接口

    接口:SmartLifecycle(https://www.jianshu.com/p/7b8f2a97c8f5)

  2. STM32中操作寄存器GPIOB_CRL &= ~( 0x0F<< (4*0))与GPIOB_CRL &=~(0x0F)之间有什么区别吗?

    没有区别,作用相同.只是这样写便于修改和沿用. 对于只用到PB0端口的程序~(0x0f << (4*0)) 和~0x0f没有区别.0x0f <<(4*N) 就是 向左 移动N个 ...

  3. JBOSS未授权访问漏洞利用

    1. 环境搭建 https://www.cnblogs.com/chengNo1/p/14297387.html 搭建好vulhub平台后 进入对应漏洞目录 cd vulhub/jboss/CVE-2 ...

  4. 2020BUAA软工个人博客作业

    2020BUAA软工个人博客作业 17373010 杜博玮 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人博客作业 我在这个课程的目标是 学 ...

  5. Noip模拟71 2021.10.7

    T1 签到题 结论题,找到规律就会做 规律是每个点的度数$\mod$颜色种数,如果不是$0$则贡献一个答案 1 #include<bits/stdc++.h> 2 #define int ...

  6. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  7. linux中dd命令

    转载:https://www.runoob.com/linux/linux-comm-dd.html Linux dd 命令用于读取.转换并输出数据. dd 可从标准输入或文件中读取数据,根据指定的格 ...

  8. 整数转化 牛客网 程序员面试金典 C++ Python

    整数转化 牛客网 程序员面试金典 C++ Python 题目描述 编写一个函数,确定需要改变几个位,才能将整数A转变成整数B. 给定两个整数int A,int B.请返回需要改变的数位个数. 测试样例 ...

  9. 2021CCPC河南省省赛

    大一萌新,第一次打比赛,虽然是线下赛,但送气球的环节还是很赞的! 这里主要是补一下自己的弱项和考试时没有做出来的题目. 1002(链接之后再放,官方还没公开题目...) 先说一下第二题,这个题一看就是 ...

  10. html5的Message信息提示框

    1.定义dialog <dialog id="showDialog"> <div>您没有权限访问本页面!</div> </dialog&g ...