为什么要有复合索引?

什么是索引

要理解索引,你需要在脑中有个画面,这里建议想象一本食谱,不是普通食谱,而是5000页的厚重食谱,包含各种场合、菜肴和季节的食谱。虽然这个食谱很全,但是它有个缺点就是它是乱序的,第一页可能是鱼香茄子,第3000页是红烧茄子。

这还不是很要紧,关键问题是这本食谱没有索引!

下面是你要问自己的第一个问题:如果没有索引如何在食谱中找到糖醋排骨?唯一的选择是一页一页翻过去,如果它在3892页,你得要翻多少页呀,最坏的情况是它在最后一页,你就得把整本书都翻一遍。

解决办法就是构建一个索引。

我们可以想到多种查找方法,其中食谱名称可以作为一个起点。如果建立一个按食谱名称排列列表,随后是其所在页码,那么就是按食谱名称对书建立索引了。其中的条目可能是这样的:

红烧排骨 : 45
猪肉饺子 : 320
酱萝卜 : 199

现在只要知道食谱的名称就能通过该索引快速找到书中的任意食谱了,如果你只希望通过这种方式来检索食谱,那就已经完事儿了。

但这是不现实的,比方说,你还会希望根据你冰箱里面的食材查找食谱,或者是根据菜肴来进行查找。针对这种情况,你需要更多的索引。

这就产生了第二个问题,只有一个基于食谱名称的索引,如何能找到所有的排骨相关的食谱呢?缺少合适的索引,你仍然需要翻阅整本食谱--5000页。在根据食材或者菜肴进行检索时都是如此。

为此我们需要构建另一个索引,这次是对食材进行索引,在这个索引里面按照字母顺序排列食材,每个食材都指向所有包含它的食谱所在的页码。最基本的食材索引是这样的

牛肉 : 301, 342, 785, 2310, 2456, 4310 ...
山药 : 8, 20, 45, 78, 287, 1295, 4587 ...
猪肉 : 12, 124, 320, 890, 3719, ...

这是你希望的索引吗?是不是很有用?

如果只是需要知道指定食材的食谱清单,这个索引就够用了,但如果还希望在查找时包含任何任意其他与与食谱相关的信息,还是需要进行“扫描”--一旦知道牛肉的页码,你要翻到每一页找到食谱的名字以及确定菜肴类型,虽然这比我们翻阅整本书要好,但是还远远不够。

例如,一周前,你无意间在这本食谱里面发现了一个很棒的鸡肉料理食谱,但是却忘了它的名字,你很想找到它然后做给你心仪的漂亮小姐姐吃。目前为止,有两个索引,一个时食谱名称的索引,另一个是食材的索引。是否能将两者结合起来,找到遗忘的鸡肉食谱呢?

实际上,这是不可能的。如果从食谱名称索引入手,但是却不记得名字,检索这个索引只比翻阅全书好一点点。从食材入手,则要检查一系列页码,但是这些页码无法插入基于食谱名称的索引。因此这种情况下只能使用一个索引,本例中食材的索引要更有用一点。

通常认为一个查询里面要查找两个字段,可以针对它们分离索引。有一个现成的算法:查找每个索引里匹配项的页码,针对同时匹配两个索引的名单扫面它们页码的交集。这样可以减少扫描的总数。一些数据库实现了这个算法,但MongoDB中没有。就算它实现了,使用复合索引来查找两个字段总是会比我刚才描述的算法效率高。请记住每个查询中数据库只会使用一个索引,如果要对多个字段进行查询,请确保有这些字段的符合索引。

那该怎么办?幸好我们有复合索引。

复合索引

目前为止你建立的都是单键索引:它们只是对食谱的一个键进行索引。现在要为整本食谱构建一个新的索引,不同之处这次是要使用两个键。类似的使用多个键的索引成为复合索引(compound index)。

该复合索引依次使用了食材和食谱名称,可以这样来标记它: 材料-食谱,其中的部分内容如下所示:

猪肉:
  猪肉白菜炖粉条: 320
  猪肉蛋卷: 3719
  猪肉脯: 890

鸡腿:
  红烧鸡腿: 82
  可乐鸡腿: 3710
  土豆焖鸡腿: 2578

西红柿
  西红柿炒鸡蛋: 4827
  西红柿鸡蛋汤: 2478
  西红柿牛腩: 489

这个索引的值对人是显而易见的,现在可以根据食材进行查找,大致定位要找的食谱,哪怕只是记得名称的开头部分。对机器而言同样很有价值,不用扫描该食材的全部食谱名称了。

需要注意的是复合索引的的顺序是很有讲究的,假设将上述索引翻转为 食谱-材料,它能替代我们之前的索引吗?

明显不能!使用新索引,只要知道名称,搜索就一定会定位到一个食谱,书中的一页。如果是要查找含有香蕉食材的猪肉食谱,那就可以确定不存在这个食谱。如果进行翻转之后,我们就必须要知道食谱的名称,在去找食材,但是现实情况往往是我们知道食材却不知道食谱名称。

现在整本食谱有三个索引: 食谱食材食材-食谱,也就是说我们可以安全地去掉食材这个索引了。为什么呢?
因为对某一食材的索引可以使用食材-食谱索引,如果你知道食材,可以便利该复合索引,获得包含它的食谱的页码列表。

总结

本文只是为更进一步认识索引提供一个隐喻,从中可以认识到一些简单的经验法则,如下:

  1. 索引能够显著减少获取文档所需的工作量。没有合适的索引,实现查询的唯一途径就是线性扫描整个文档,直到满足查询条件为止。这通常就是扫描整个集合。
  2. 解析查询时只会使用一个单键索引(or是例外),对于包含多个键(比如食材和食谱)的查询,包含这些键的复合索引能更好地解析查询。

比如student表,对age和name都建立了索引,如果你查询name="zhangsan" and age = 20,也只是会使用其中一个索引

  1. 如果有食材-菜谱索引,可以去掉食材索引,也应该这么做。更抽象一点,如果有一个a-b的复合索引,那么仅针对a的索引就是冗余的。但是如果b本身就是一个复合索引(b=c-d),那么同时拥有a-b和a还是很有意义的。
  2. 符合索引里键的顺序也是很重要的。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 一、简介 索引(在MySQL中也叫做“键(key)”),是存储引擎用于快速找到记录的一种数据结构。 索引类似于书籍...
    四月不见阅读 1,102评论 0 2
  • 索引 数据库中的查询操作非常普遍,索引就是提升查找速度的一种手段 索引的类型 从数据结构角度分 1.B+索引:传统...
    一凡呀阅读 2,862评论 0 8
  • 索引是应用程序设计和开发的一个重要方面。 若索引太多, 应用程序的性能可能会受到影响。 而索引太少, 对查询性能又...
    好好学习Sun阅读 1,030评论 0 4
  • SQL SERVER提供了多种索引。如果以存储结构结构来区分,有聚集索引和非聚集索引;如果以数据的唯一性来区分,则...
    不知名的蛋挞阅读 6,027评论 0 5
  • 已然是温暖的春天了,春姑娘用和煦的春风送走了冬的严寒,春姑娘用温暖的春风吹开了朵朵娇艳的花! 晚饭后,出...
    lotus若莲阅读 325评论 0 2