es怎么对应mysql es mysql( 三 )


在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论是MyISAM和InnoDB两个存储引擎的B+Tree索引的实现方式 。
MyISAM引擎使用B+Tree作为索引结构 , 叶节点的data域存放的是数据记录的地址,下面是MyISAM索引的原理图:
上图是一个MyISAM表的主索引示意,可以看出MyISAM的索引文件仅仅保存数据记录的地址,在MyIASM中 , 主索引和辅助索引在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复 。B+Tree的所有叶子节点包含所有关键字且按照升序排列的 。
MyISAM表的索引和数据是分离的 , 索引保存在“表名.MYI”文件内 , 而数据保存在“表名.MYD”中 。
MyISAM的索引方式也叫做 非聚集 的,之所以这么称呼是为了与InnoDB的聚集索引区分 。
虽然InnoDB也使用B+Tree作为索引结构,但是具体实现方式却与MyISAM截然不同 。
第一个重大区别是InnoDB的数据文件本身就是索引文件 , 从上文知道MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录地址,而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构 , 这棵树的叶节点data域保存了完整的数据记录 , 这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引 。
上图是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录 。这种索引叫做 聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显示指定,则MySQL系统会自动选择一个唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段为主键,这个字段长度为6字节,类型为长整形 。
第二个与MyISAM索引的不同时InnoDB的辅助索引data域存储相应记录主键值而不是地址,换句话说,InnoDB的所有辅助索引都引用主键作为data域,例如,下图定义在col3上的辅助索引:
这里的英文字符的ASCII码作为比较准则 。聚集索引这种方式使得按照主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键索引到主索引中检索获取记录 。
了解不同存储引擎的索引实现对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引 , 过长的主索引会令辅助索引变的更大 ,在例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree非单调的主键会造成在插入新纪录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择
ES的索引不是B+Tree树,而是倒排索引,ES的倒排索引由 Term index,Term Dictionary和Posting List 组成的 。
有倒排索引(inverted index)就用正排索引(forward index),正排索引就是文档(Document)和他字段Fields正向对应的关系对应表如下:
那么倒排索引是字段Field和拥有这个Field的文档对应的关系如下:
Sex字段:
Age字段:
Jack、lucy或者17,18叫做term , 而[1,3]就是Posting list 。Posting list就是一个int数组,存储了所有包含某个term的文档id,那么什么是term index和term dictionary?
如上如果name字段很多个term , 比如Carla,Sara,Elin,Ada,Patty,Kate,Selena,如果按照这样的顺序排列,找出某个特定的term一定很慢,因为term没有排序,需要全部过滤一遍,才能找出特定的term 。排序之后就变成了:Ada,Carla,Elin,Kate,Patty,Sara,Selena 。

推荐阅读