MySQL和Lucene都可以对数据构建索引并通过索引查询数据,一个是关系型数据库,一个是构建搜索引擎(Solr、ElasticSearch)的核心类库。两者的索引(index)有什么区别呢?以前写过一篇《Solr与MySQL查询性能对比》,只是简单的对比了下查询性能,对于内部原理却没有解释,本文简单分析下两者的索引区别。

MySQL索引实现

在MySQL中,索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,本文主要讨论MyISAM和InnoDB两个存储引擎的索引实现方式。

MyISAM索引实现

MyISAM引擎使用B+Tree作为索引结构,叶节点的data域存放的是数据记录的地址。下图是MyISAM索引的原理图:

图1是一个MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引文件仅仅保存数据记录的地址。在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求key是唯一的,而辅助索引的key可以重复。B+Tree的所有叶子节点包含所有关键字且是按照升序排列的。

MyISAM表的索引和数据是分离的,索引保存在”表名.MYI”文件内,而数据保存在“表名.MYD”文件内。

MyISAM的索引方式也叫做“非聚集”的,之所以这么称呼是为了与InnoDB的聚集索引区分。

InnoDB索引实现

虽然InnoDB也使用B+Tree作为索引结构,但具体实现方式却与MyISAM截然不同。

第一个重大区别是InnoDB的数据文件本身就是索引文件。从上文知道,MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。

图2是InnoDB主索引(同时也是数据文件)的示意图,可以看到叶节点包含了完整的数据记录。这种索引叫做聚集索引。因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有),如果没有显式指定,则MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整形。

第二个与MyISAM索引的不同是InnoDB的辅助索引data域存储相应记录主键的值而不是地址。换句话说,InnoDB的所有辅助索引都引用主键作为data域。例如,图3为定义在Col3上的一个辅助索引:

这里以英文字符的ASCII码作为比较准则。聚集索引这种实现方式使得按主键的搜索十分高效,但是辅助索引搜索需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。

了解不同存储引擎的索引实现方式对于正确使用和优化索引都非常有帮助,例如知道了InnoDB的索引实现后,就很容易明白为什么不建议使用过长的字段作为主键,因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。再例如,用非单调的字段作为主键在InnoDB中不是个好主意,因为InnoDB数据文件本身是一颗B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持B+Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。

讲MySQL索引的实现的文章很多,以上也是参考了《MySQL索引背后的数据结构及算法原理》,现在来看看Lucene的索引原理。

Lucene索引实现

Lucene的索引不是B+Tree组织的,而是倒排索引,Lucene的倒排索引由Term index,Team Dictionary和Posting List组成。

有倒排索引(invertedindex)就有正排索引(forwardindex),正排索引就是文档(Document)和它的字段Fields正向对应的关系:

DocID

name

sex

age

1

jack

18

2

lucy

17

3

peter

17

倒排索引是字段Field和拥有这个Field的文档对应的关系:

Sex字段:

[1,3]

[2]

Age字段:

18

[1]

17

[2,3]

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

这样就可以用二分查找的方式,比全遍历更快地找出目标的term。如何组织这些term的方式就是 Term dictionary,意思就是term的字典。有了Term dictionary之后,就可以用比较少的比较次数和磁盘读次数查找目标。但是磁盘的随机读操作仍然是非常昂贵的,所以尽量少的读磁盘,有必要把一些数据缓存到内存里。但是整个Term dictionary本身又太大了,无法完整地放到内存里。于是就有了Term index。Term index有点像一本字典的大的章节表。比如:

A开头的term ……………. Xxx页

C开头的term ……………. Xxx页

E开头的term ……………. Xxx页

如果所有的term都是英文字符的话,可能这个term index就真的是26个英文字符表构成的了。但是实际的情况是,term未必都是英文字符,term可以是任意的byte数组。而且26个英文字符也未必是每一个字符都有均等的term,比如x字符开头的term可能一个都没有,而s开头的term又特别多。实际的term index是一棵trie 树:

上图例子是一个包含 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn" 的trie树。这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。再加上一些压缩技术(想了解更多,搜索 Lucene Finite State Transducers),Term index的尺寸可以只有所有term的尺寸的几十分之一,使得用内存缓存整个term index变成可能。整体上来说就是这样的效果:

由Term index到Term Dictionary,再到Posting List,通过某个字段的关键字去查询结果的过程就比较清楚了,通过多个关键字的Posting List进行AND或者OR进行交集或者并集的查询也简单了。

对比MySQL的B+Tree索引原理,可以发现:

1)Lucene的Term index和Term Dictionary其实对应的就是MySQL的B+Tree的功能,为关键字key提供索引。Lucene的inverted index可以比MySQL的b-tree检索更快。

2)Term index在内存中是以FST(finite state transducers)的形式保存的,其特点是非常节省内存。所以Lucene搜索一个关键字key的速度是非常快的,而MySQL的B+Tree需要读磁盘比较。

3)Term dictionary在磁盘上是以分block的方式保存的,一个block内部利用公共前缀压缩,比如都是Ab开头的单词就可以把Ab省去。这样Term dictionary可以比B-tree更节约磁盘空间。

4)Lucene对不同的数据类型采用了不同的索引方式,上面分析是针对field为字符串的,比如针对int,有TrieIntField类型,针对经纬度,就可以用GeoHash编码。

5)在 Mysql中给两个字段独立建立的索引无法联合起来使用,必须对联合查询的场景建立复合索引,而Lucene可以任何AND或者OR组合使用索引进行检索。

参考:

http://stackoverflow.com/questions/4628571/solr-date-field-tdate-vs-date

http://lucene.apache.org/core/

本文转自阿凡卢博客园博客,原文链接:http://www.cnblogs.com/luxiaoxun/p/5452502.html,如需转载请自行联系原作者

mysql lucene 索引区别_MySQL和Lucene索引对比分析相关推荐

  1. mysql 唯一索引和复合索引 区别_MySQL复合唯一索引分析

    MySQL复合唯一索引分析 关于复合唯一索引(unique key 或 unique index),网上搜索不少人说:"这种索引起到的关键作用是约束,查询时性能上没有得到提高或者查询时根本没 ...

  2. u2 接口 服务器硬盘,U2和M2硬盘接口区别介绍 固态硬盘接口优缺点对比分析

    U2和M2硬盘接口区别介绍,固态硬盘接口优缺点对比分析,大家都知道固态硬盘SATA3.0接口是目前主流,但是M.2和U.2两种接口.那么U.2和M.2接口发展很快.下面小编为大家介绍下M.2和U.2接 ...

  3. u2硬盘测试软件,U2和M2硬盘接口区别介绍 固态硬盘接口优缺点对比分析

    U2和M2硬盘接口区别介绍,固态硬盘接口优缺点对比分析,大家都知道固态硬盘SATA3.0接口是目前主流,但是M.2和U.2两种接口.那么U.2和M.2接口发展很快.下面小编为大家介绍下M.2和U.2接 ...

  4. mysql几种索引类型_Mysql几种索引类型的区别及适用情况

    如大家所知道的,Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE. 那么,这几种索引有什么功能和性能上的不同呢? FULLTEXT 即为全文索引,目前只有MyI ...

  5. mysql btree检索策略_MySQL之Btree索引和HASH索引的区别以及索引优化策略

    索引是帮助mysql获取数据的数据结构.最常见的索引是Btree索引和Hash索引. 不同的引擎对于索引有不同的支持:Innodb和MyISAM默认的索引是Btree索引:而Mermory默认的索引是 ...

  6. mysql唯一索引和联合索引的区别_mysql中,索引,主键,唯一索引,联合索引的区别...

    索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针. 普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度. ...

  7. mysql 隐藏中间四位_MySQL知识体系——索引

    本文直切主题,针对InnoDB引擎描述索引及优化策略.在开始之前,需要读者了解: 二叉查找树(包括2-3查找树.红黑树等数据结构) MySQL的InnoDB引擎基础知识 索引初探 要了解索引,当然要了 ...

  8. mysql数据库最多列_mysql多列索引和最左前缀

    数据库的索引可以加快查询速度,原因是索引使用特定的数据结构(B-Tree)对特定的列额外组织存放,加快存储引擎(索引是存储引擎实现)查找记录的速度. 索引优化是数据库优化的最重要手段. 如果查询语句使 ...

  9. mysql索引教程_MySQL教程96-MySQL索引类型

    索引的类型和存储引擎有关,每种存储引擎所支持的索引类型不一定完全相同.MySQL 索引可以从存储方式.逻辑角度和实际使用的角度来进行分类. 存储方式区分 根据存储方式的不同,MySQL 中常用的索引在 ...

最新文章

  1. Factory-pattern 三种工厂模式
  2. MS SQL 维护小记
  3. Sun x4500作为文件服务器的调优
  4. go语言之进阶篇主协程先退出导致子协程没来得及调用
  5. java开发用怎么软件开发_Java 9中的5个功能将改变您开发软件的方式(还有2个不会)...
  6. 这篇文章可以满足你80%日常工作!成功入职腾讯
  7. LeetCode 695. 岛屿的最大面积(图的BFS/DFS)
  8. Bezier(贝塞尔)曲线(三阶)的轨迹规划在自动驾驶中的应用(四)
  9. STM32:定时器中断与优先级
  10. 作为程序员,你还在用B站学习?别做梦了
  11. 杭电多校HDU 6601 Keen On Everything But Triangle(主席树)题解
  12. Oracle下载12c安装包
  13. 基于IOS的仿微博系统
  14. python:BeautifulSoup解析爬取网页文章demo
  15. android相机固定焦距,android Camera 设置焦距
  16. 如何识别服务器连接的偶发故障?
  17. 《地球帝国2》中文版秘籍
  18. 十次方:服务器的1U、2U、U代表什么意思?
  19. python——基础题
  20. 25万英汉词典汉英词典ACCESS\SQLite3数据库

热门文章

  1. 在华为云ECS上部署openGauss
  2. 【老九学堂】【C++】数组与指针
  3. 寒武纪行歌 - 智能驾驶大算力芯片入局者
  4. 【转载】浅析金庸武侠小说中的哲理意蕴
  5. 吴恩达深度学习课后编程题讲解(python)
  6. c语言.jpg图片转成数组_基于 C 语言开发的 GUI 框架
  7. python:map_reduct_filter_sorted
  8. 单片机四个按键做加减乘除功能
  9. 致得E6协同文档管理软件 推出4.0免费版
  10. 日本教育家多湖辉的《学生用功术》 (1)