`
王之子
  • 浏览: 106267 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

关于组合索引

阅读更多

大多数书的目录中会列出“章”和“节”,这便是组合索引。

在实际的数据库访问中,大多数的查询都包含组合条件,比如:

 

... where a = 1 and b = 2

... where a = 1 order by b

... where a = 1 group by b

 

这个时候,即使字段 a 和字段 b 已经分别建立了索引,它们仍然不能同时发挥作用,因为一次查询对于一个数据表只能使用一个索引,它们是无法进行效用叠加的。这样一来,便会存在一定程度的局部行扫描(Range Scan),这在有些特定的场景中将严重影响查询性能,比如上述第一条查询,数据库会先利用字段a的索引快速匹配a=1的记录,然后在这些记录中帅选b=2的记录,而此时b字段的索引将爱莫能助,试想,如果a=1的匹配行非常多的话,查询时间将花在b字段的帅选操作上。

为了应付这样的查询,我们不得不使用组合索引。

 

我们来创建这样一个数据表:

CREATE TABLE `key_t` (
  `id` int(11) NOT NULL,
  `key1` int(11) NOT NULL DEFAULT '0',
  `key2` int(11) NOT NULL DEFAULT '0',
  `key3` int(11) NOT NULL DEFAULT '0',
   PRIMARY KEY (`id`),
   KEY `normal_key` (`key1`,`key2`,`key3`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

 这个数据表建立了一个包含了三个字段的组合索引 normal_key,同时它还有一个自增类型的主键。我们为这个表填充了 100 万行的记录,其中 key1、key2、key3的内容均为0到999的随机整数。

 

SELECT COUNT(*) FROM `key_t`

 

我们知道以下几个查询都可以直接使用 normal_key 索引,而不需要任何的行扫描。

SELECT * FROM `key_t` WHERE key1=1
SELECT * FROM `key_t` WHERE key1=1 and key2=2 
SELECT * FROM `key_t` WHERE key1=1 and key2=2 and key3=3

 必要的时候,查询优化器还会帮你调整条件表达式的顺序,以匹配组合索引的要求,比如以下这个查询:

SELECT * FROM `key_t` WHERE key1=1 and key3=3 and key2=2 

 它会被查询优化器理解为:

SELECT * FROM `key_t` WHERE key1=1 and key2=2 and key3=3

 优化器是很智能的。

 

其次,组合索引对于包含 order by 和 group by 的查询也发挥着重要的作用,它们同样也遵循最左前缀原则,我们看以下这个SQL语句的分析:



 

其中 type 为 index,表示这个查询只需要在索引中扫描即可,这里的索引即 normal_key 。也就是说,查询语句中 order by 指定的排序规则正好是索引本身的顺序,可以直接拿来派上用场,不需要重新排序。需要注意的是,有些非顺序的索引类型(如 Hash),对 order by 是无效的。

 

下面这个查询正是符合最左前缀的原则,它也使用了 normal_key 索引。

 


 

 那么,再看看下面这个SQL语句:



 虽然它用到了 normal_key 索引,但只是对 where 子句起作用,而后面的 order by 则需要排序计算,Using filesort 已经证明了这点。

 

对于包含 group by 的查询,数据库一般需要先将记录分组后放置在新的临时表中,然后分别对它们进行函数计算,比如 count()、sum() 或 max() 等。当有切当的索引存在时,group by 有时也可以使用索引来取代创建临时表,这当然是我们所希望的。以下这个 SQL 语句便利用了 normal_key 索引,避免了创建临时表。



 

而对于另外一些情况,组合索引就无法帮助 group by 了,比如以下的 SQL 语句:

 



 的确,Using temporary 和 Using filesort 非常不受欢迎,它们越少越好。

 

组合索引的副作用

在有些情况下,组合索引对于一些查询会产生误导,你需要考虑是否应该阻止组合索引,或者预先设计更加适合的索引。同样针对刚才那个数据表,我们看以下这个查询:

 

 

根据最左前缀原则,以上的查询没有可使用的索引,索引要进行全表扫描,必然花费很长的时间。但是,并不是我们想象的那样,看下面的分析:

 

 竟然使用了 normal_key 索引,而且 type 为 index ,表示这里进行了索引扫描,显然优化器认为在索引扫描中扫描要比在全表数据中扫描更加高效,但是,这次它的如意算盘打错了。仔细看,这 10 行记录是按照 key1 字段来顺序排列的,这说明查询是基于 normal_key 索引的扫描,而不是基于数据本身的扫描。Innodb 类型表中数据的存储顺序是按照主键来排列的。

 

我们在查询的尾部增加了 ORDER BY id ,结果如下所示:



 用 EXPLAIN 分析如下:

 



 由于我们指定了 order by id ,查询优化器聪明地放弃了 normal_key 索引,而使用主键进行扫描,这基本上相当于全表扫描。如果你希望结果仍然按照 key1 排序,这不是什么问题,你可以增加一个包含(key2,key1)字段的组合索引,注意它们的顺序,(key1,key2)索引和(key2,key1)索引完全不同,你必须根据需要来进行抉择,而优化器对此无能为力。

  • 大小: 24.8 KB
  • 大小: 27.7 KB
  • 大小: 26.9 KB
  • 大小: 28.3 KB
  • 大小: 32.3 KB
  • 大小: 58 KB
  • 大小: 28.6 KB
  • 大小: 66.8 KB
  • 大小: 26.8 KB
分享到:
评论

相关推荐

    MySQL组合索引与最左匹配原则详解

    什么时候创建组合索引? 当我们的where查询存在多个条件查询的时候,我们需要对查询的列创建组合索引 为什么不对没一列创建索引 减少开销 覆盖索引 效率高 减少开销:假如对col1、col2、col3创建组合索引,相当...

    易语言取组合框的顶端可见项目的索引

    今天小编就为大家分享一篇关于易语言取组合框的顶端可见项目的索引,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

    导致MySQL索引失效的一些常见写法总结

    主要给大家介绍了关于导致MySQL索引失效的一些常见写法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

    数据库设计与优化.pdf

    1.3.3 主键的设计 主键是必要的,SQL SERVER 的主键同时是一个唯一索引,而且在实际应用中,我们往往选择最小的键组合作为主键, 第 2 页 共 19 页 所以主键往往适合作为表的聚集索引。聚集索引对查询的影响是比较...

    python中pandas.DataFrame的简单操作方法(创建、索引、增添与删除)

    最近在网上搜了许多关于pandas.DataFrame的操作说明,都是一些基础的操作,但是这些操作组合起来还是比较费时间去正确操作DataFrame,花了我挺长时间去调整BUG的。我在这里做一些总结,方便你我他。感兴趣的朋友们一...

    关于R树算法的讲解

    若对多个字段进行索引,必须指定各个字段的优先级形成一个组合字段,而地理数据的多维性,在任何方向上并不存在优先级问题,因此B树并不能对地理数据进行有效的索引,所以需要研究特殊的能适应多维特性的空间索引...

    Firestore-Composite-Index-Generator:用于在Firestore中生成复合查询所需的复合索引

    在创建应用程序时,这可能意味着要为可用的排序和过滤器的每种可能组合创建一个复合索引。 例如,如果您有一个表,显示仓库中的不同汽车。 该架构将类似于: Cars (collection) { Car-ASKDN234MD (document) { ...

    个人项目:我从头开始或从所学课程中开发的有趣的数据分析和ML项目

    贾斯汀·凯斯勒(Justin Kessler)-项目组合索引该资料库保存了我多年来所做的所有个人项目。 目前,它们分为三个不同的类别 个人编程项目:Python数据科学机器学习Web抓图和地图每个类别都有各自不同的项目,并应...

    Siebel 性能微调指南 (中文版)

    管理排序和搜索中所用的数据库索引 107 重复使用标准列 108 业务对象层的最佳惯例 110 使用“高速缓存数据”属性改进业务组件的性能 110 限制处于活动状态的字段数 110 使用计算字段的准则 111 使用属性以改进选取...

    java面试常见基础(深层次,高级研发)

    17. 数据库组合索引,储存在一个叶子节点还是多个? 44 17.1. 索引的利弊与如何判定,是否需要索引: 44 17.1.1. 索引的好处 44 17.1.2. 索引的弊端 44 17.1.3. 如何判定是否须要创建索引 44 17.2. 复合索引优化 45 ...

    worldwindjava源码-github_index:github仓库索引

    关于为我的 github 存储库创建更好索引的元项目。 部分动机是因为我太贪心,无法只处理 6 个固定存储库。 它足够稳定,可以正常运行(根据我对存储库的个人约定)。 它具有我链接在一起的几个子实用程序,包括目录...

    SummerHacks-ZCoders:Vishal和Aayush投资组合

    Summer Hacks项目提交的模板项目名称:-SummerHacks-Portfolio目录:-关于照片联系信息的索引(指向各个平台的链接)关于:-我们的两名成员(Vishal Kumar Singh和Aayush Verma)的投资组合学到的知识:-面临HTML和...

    阿里巴巴编码规范 基础技能认证 考题分析(考题+答案).docx

    业务上具有唯一特性的字段(含组合字段),必须指定唯一索引。 D .建复合索引时,一般选择区分度高的字段放在最左列。 多选 13.关于二方库版本号的命名方式,下列哪些说法符合《阿里巴巴Java开发手册》:ABCD A...

    goGPS-MATLAB

    关于 安装 需求 安装程序 goGPS目录 执行 设置 目录索引 菜单 侧边栏 选项卡 先进的 资源 命令 数据源 接收方的信息 预处理 处理 参数化购买力平价 参数化网络 大气 底栏 命令语言 目录索引 接收机数据组织 最小的...

    VC++组合逻辑仿真器源码附文档(毕业设计)

    内容索引:VC/C++源码,其它分类,仿真器 毕业设计时做的,主要参考的是:Electronics Workbench这个软件。程序由几个大模块组成:元件数据结构模块,电路图编辑模块,元件库模块,计算结果(仿真)模块。  关于指针...

    melikechan.github.io:我的投资组合和关于我的网站

    11.3.20:填充页面,创建的模板索引页面,固定的导航栏。 12.18.20:开始进入Bootstrap,并将navbar更改为Bootstrap navbar。 1.17.21:添加了项目页面并更改了网站图标的背景。 1.27.21:完全上传了第一个基础...

    VChooseK:从向量中选择 K 个元素 - MEX:比 NCHOOSEK 快 100 倍-matlab开发

    VchooseK(V, K) 创建一个矩阵,其中的行都是选择向量 V 的 K 个元素的组合,无序无重复。 输入: V:DOUBLE、SINGLE、(U)INT8/16/32/64、LOGICAL、CHAR 类的数组。 K:要选择的元素数。 输出: Y:大小为 [N!/K!...

    关于对称无痕张量模型的大N极限

    当假定四元相互作用具有特殊的四面体索引结构时,耦合常数g必须在大旋律N极限内缩放为N -3/2。 在本文中,我们考虑了一个具有四面体四次相互作用的完全对称且无迹的3级张量的大N理论的组合。 该模型具有单个O(N)...

    mobile_resp_portfolio

    索引(关于)页面 投资组合页面 联系页面 安装/依赖 无需先决条件或浏览器修改即可在此处在线运行页面。 如果要克隆项目: $ git clone :CalderonJG / mobile_resp_portfolio.git 学分 作者 何塞·卡德隆三世(@...

Global site tag (gtag.js) - Google Analytics