我们都知道,当数据表中的数据日益增长后,查询会变得越来越慢,当初在表设计之初,尚未考虑创建索引的话,那么现在正是必要的时候。可是,如果对于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. PTA数据结构 习题2.8 输出全排列 (20分)

    习题2.8 输出全排列 (20分) 请编写程序输出前n个正整数的全排列(n<10),并通过9个测试用例(即n从1到9)观察n逐步增大时程序的运行时间. 输入格式: 输入给出正整数n(<10 ...

  2. NX Open显示符号(UF_DISP_display_temporary_point)

    UF_DISP_display_temporary_point 使用方法: 1 Dim x As Double = 0, y As Double = 0, z As Double = 0 2 3 Di ...

  3. 用C++实现的数独解题程序 SudokuSolver 2.4 及实例分析

    SudokuSolver 2.4 程序实现 本次版本实现了 用C++实现的数独解题程序 SudokuSolver 2.3 及实例分析 里发现的第三个不完全收缩 grp 算法 thirdGreenWor ...

  4. python进阶(21)typing模块--类型提示支持

    typing介绍   Python是一门弱类型的语言,很多时候我们可能不清楚函数参数的类型或者返回值的类型,这样会导致我们在写完代码一段时间后回过头再看代码,忘记了自己写的函数需要传什么类型的参数,返 ...

  5. elasticsearch的dsl查询

    测试es的dsl查询,准备数据,在插入数据的时候,如果index.type.mapping都没有,es会自动创建 一.数据的准备 curl -XPOST "http://192.168.99 ...

  6. 洛谷 P5657 [CSP-S2019] 格雷码

    链接: P5657 分析: 签到题,不过也有不少细节. 数据范围需要开 unsigned long long ,前年也有很多人因此丢了5分. pow 会出现神必错误,需要手写一个 mpow 函数. 算 ...

  7. 【代码更新】单细胞分析实录(20): 将多个样本的CNV定位到染色体臂,并画热图

    之前写过三篇和CNV相关的帖子,如果你做肿瘤单细胞转录组,大概率看过: 单细胞分析实录(11): inferCNV的基本用法 单细胞分析实录(12): 如何推断肿瘤细胞 单细胞分析实录(13): in ...

  8. xUtils3的使用教程

    首先在build.gradle下的dependencies下添加引用. implementation 'org.xutils:xutils:3.3.36' 然后创建一个表实体. package com ...

  9. 两个栈实现队列 牛客网 剑指Offer

    两个栈实现队列 牛客网 剑指Offer 题目描述 用两个栈来实现一个队列,完成队列的Push和Pop操作. 队列中的元素为int类型. class Solution: def __init__(sel ...

  10. Hdu P1394 Minimum Inversion Number | 权值线段树

    题目链接 题目翻译: 约定数字序列a1,a2,...,an的反转数是满足i<j和ai>aj的数对(ai,aj)的数量. 对于给定的数字序列a1,a2,...,an,如果我们将第1到m个数字 ...