elasticsearch入门篇:数据存储方式研究:lucene索引的原理(理论入门)

mysql数据库最左前缀匹配原则的温习:
联合索引(product_code,pkg_code,name) ,B+树是按照从左到右的顺序来建立搜索树的。如('123456789','12345','xxx')来检索数据的时候,B+树会优先匹配product_code来确定搜索方向,product_code匹配成功再依次匹配pkg_code、name。
但是如果拿 (‘12345’,'xxx')来检索时,B+树没有拿到一级索引,根本就无法确定下一步的搜索方向。('123456789,'xxx')这种场景也是一样,当product_code匹配成功后,没有pkg_code这个二级索引,只能在product_code相同的情况下,去遍历所有的name。
like '%xxx%'不会使用索引,而like ‘xxx%’可以使用索引。

接下来考虑这样一个场景:用户在搜索框输入xxx,希望自动提示包含xxx字样的提示词。在数据库中搜索包含“xxx”字样的数据,那么就注定要使用select product_code, pkg_code, name from items where product_code='12345678' and pkg_code='12345' and name like '%xxx%';
这里一级索引和二级索引还是生效的,但是接下来的模糊搜索就要扫描所有的product_code='12345678' and pkg_code='12345' 的数据了,即便是给name建了索引也用不上。

索引的核心是排序,而大部分的搜索(数据库)引擎都是用B+树结构来维护索引,索引的更新会导致大量的IO操作,同时对整个B+树结构进行调整,我们需要寻求一种高效的索引方式。

Lucene就可以用于解决这种问题。它解决问题的方式是在扩展索引的时候不断创建新的索引文件,然后定期的把这些新的小索引文件合并到原先的大索引中,这样在不影响检索的效率的前提下。
首先从原文提取分词,排序顺序存储的同时,有另外一个排好序的关键词列表,首先是要分词:北京年度版宠物狗一年期,就会把它分为北京、年度版、宠物狗、一年期等词汇。
然后开始建立索引文件,建立索引文件的过程,实际就是把documents文件一个个加入索引中,Lucene的做法是最开始为每个新加入的document独立生成一个segment,放在内存中。而后,当内存中segments数量到达一个阙值时,合并这些segments,新生成一个segment加入文件系统的segments列表中。
每个索引文件都是一个完整的segments索引文件,在搜索时,Lucene会遍历这些segments,以segments为基本单位独立搜索每个segments文件,而后再把搜索结果合并。

将源中需要的信息加入Document的各个Field中,并把需要索引的Field索引起来,把需要存储的Field存储起来。
用户提供搜索关键词,经过analyzer处理。对处理后的关键词搜索索引找出对应的Document。用户根据需要从找到的Document中提取需要的Field。

两个文档, doc1和doc2他们的内容分别如下:

Doc1: 北京年度版宠物狗一年期

Doc2: 广州年度版二手车半年期

如果按照正常的索引建立如下所示:

文档名 关键字 次数

Doc1 北京       1

Doc1 年度版       1

Doc2 广州     1

Doc2 年度版       1

……

这里索引的建立是以文档为标准的, 即“document包含哪些单词”。

这样当文档很多的时候数据量将非常的大, 检索效率会明显下降的。

倒排索引是以单词为标准来进行索引的建立的,即“哪个document包含单词x”。还以上面的doc1和doc2为例:

关键字 出现的文档 次数

北京     doc1           1

广州    doc2            1

年度版  doc1   1

    doc2   1

……

这样当你想要查询年度版的时候就只搜索doc1和doc2,而当你想要搜广州的时候就只需搜索doc2。减少了文档搜索的数量。

 下篇文章会结合代码和一个例子来解释索引。

猜你喜欢

转载自www.cnblogs.com/buqingyuan/p/10419225.html