上一篇:WEBUS2.0 In Action - 搜索操作指南(3)

6. 搜索多个索引

为了提升性能, 我们可以从多个索引同时进行搜索, Webus.Search.MultiSearcher提供了相关功能:

public MultiSearcher(ISearcher[] searchers) {...}

我们将多个ISearcher对象传入MultiSearcher, 就可以像操作一个ISearcher对象那样进行搜索了.

IIndexer idx1 = new IndexManager();
idx1.Open(@"c:\index1");
IIndexer idx2 = new IndexManager();
idx2.Open(@"c:\index2");
ISearcher se1 = new IndexSearcher(idx1);
ISearcher se2 = new IndexSearcher(idx2);
ISearcher se = new MultiSearcher(new ISearcher[] { se1, se2 });
var result = se.Search("Title=\"key\"");

由于MultiSearcher本身特性的限制, 如下方法和属性是不被支持的:

public int MinDocId
public int MaxDocId
public void Open(string indexPath)
public void Open(Webus.IO.IDirectory dir)
public Document SelectDoc(int docId)
public Document SelectDoc(int docId, string[] fieldnames)
public List<Document> SelectDoc(int[] docIds)
public List<Document> SelectDoc(int[] docIds, string[] fieldnames)

值得注意的是, MultiSearcher会顺序调用所有的子搜索, 是顺序运行而非并发运行. 如果索引文件都在同一个物理磁盘上, 顺序运行的方式往往可以获得更好的性能. 不过如果我们有多块磁盘, 并且索引分别保存在不同的磁盘上, 那么我强烈推荐使用另外一种并发的搜索方式: Webus.Search.ParallelSearcher

public ParallelSearcher(ISearcher[] searchers) {...}

调用方式如下:

IIndexer idx1 = new IndexManager();
idx1.Open(@"c:\index1"); //索引index1在C盘, C盘是物理磁盘1#
IIndexer idx2 = new IndexManager();
idx2.Open(@"d:\index2"); //索引index2在D盘, D盘是物理磁盘2#
ISearcher se1 = new IndexSearcher(idx1);
ISearcher se2 = new IndexSearcher(idx2);
ISearcher se = new ParallelSearcher(new ISearcher[] { se1, se2 });
var result = se.Search("Title=\"key\"");

这个时候两块物理磁盘1#, 2#不会发生争用, 查询性能是能够得到明显提升的.

7. 缓存搜索结果

内存存取速度是硬盘的100倍以上. 正因为这个原因, 磁盘索引永远不可能比内存索引快. 因此我们需要为搜索结果添加缓存来改善我们的应用程序性能. 为此WEBUS2.0 SDK提供了Webus.Searcher.CacheSearcher来实现搜索缓存的功能.

public CacheSearcher(IQueriable indexer) {...}
public ICacher<string, Webus.Search.Hits> QueryCacher { get; set; }
public ICacher<int, Webus.Documents.Document> DocCacher { get; set; }
public ICacher<string, Webus.Documents.Field> FieldCacher { get; set; }

在反复对10万数据级别的索引进行测试之后, 我们发现了如下三种缓存最能够提升性能:

Query Cache
对Search的结果进行缓存, 这些结果是最终结果. 这个缓存使用LRU算法进行调度, 同时由后台线程进行更新维护.

Doc Cache
通过分析索引中原始关键词的结果分布情况, 按照出现频率由高到低进行缓存. 这种缓存可以明显的改善数据加载性能, 其覆盖率与改善效果成正比. 这个缓存属于静态缓存, 数据一次性预加载到系统中.

Field Cache
通过预先加载可排序字段的值来提高排序性能. 这个缓存按照DocId由大到小进行加载. 也属于静态缓存, 数据一次性预加载到系统中. 值得注意的是, 这个缓存会尽量利用Doc Cache中已有的缓存数据来提高效率, 减少内存空间占用率.

不论是QueryCache, DocCache还是FieldCahce, 都是ICacher类型, WEBUS中提供了两个ICahcer的实现:

Webus.Search.Caches.LRUCacher - 近期最少使用缓存

Webus.Search.Caches.LRUExpiryCacher - 近期最少使用过期缓存

关于LRU算法, 网上有很多解释, 可以参照 http://baike.baidu.com/view/70151.htm

至于LRUExpiry算法, 其实是在LRU的基础上增加过期策略, 并利用后台线程实时释放过期的缓存项目, 从而减小内存占用. 属于一种增强型算法.

使用CacheSearcher的示例代码如下:

IIndexer idx = new IndexManager();
idx.Open(@"c:\index");
CacheSearcher se = new CacheSearcher(idx);
se.QueryCacher = new LRUCacher(1000); //MaxSize=1000
se.DocCacher = new LRUCacher(1000);
se.FieldCacher = new LRUCacher(1000);
var result = se.Search("Title=\"key\"");

不论是LRUCacher还是LRUExpiryCacher, 我们可以通过指定缓存条目数(MaxSize)来限制内存占用. 需要注意的是这两种算法并非严格的遵循MaxSize的限制, 有时候也会可能超过这个限制, 但是马上会被后台维护线程发现并将需要淘汰的项目清除掉, 直至恢复到MaxSize之下.

至此, WEBUS2.0搜索部分就全部介绍完了. 在搜索操作指南 - (1) 到 (4)中, 我们分别介绍了如下主题:

  • IQueriable内置的搜索功能
  • Query对象的使用
  • 对搜索结果进行评分, 排序和过滤
  • 搜索多个索引 (顺序, 并发)
  • 缓存搜索结果

希望能够有所帮助. WEBUS2.2.3.9已经发布, 赶快集成到你的程序中去吧! 下载地址

相关信息及WEBUS2.0 SDK下载:继续我的代码,分享我的快乐 - WEBUS2.0

访问我们的站点: www.gdtsearch.com

WEBUS2.0 In Action - 搜索操作指南 - (4)的更多相关文章

  1. WEBUS2.0 In Action - 搜索操作指南 - (1)

    上一篇:WEBUS2.0 In Action - 索引操作指南(2) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(2) 1. IQueriable中内置的搜索功能 在Webus ...

  2. WEBUS2.0 In Action - 搜索操作指南 - (2)

    上一篇:WEBUS2.0 In Action - 搜索操作指南(1) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(3) 2. 使用Query Query是所有查询的基类, 它一 ...

  3. WEBUS2.0 In Action - 搜索操作指南 - (3)

    上一篇:WEBUS2.0 In Action - 搜索操作指南(2) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(4) 3. 评分机制 (Webus.Search.IHitSc ...

  4. WEBUS2.0 In Action - 索引操作指南(2)

    上一篇:WEBUS2.0 In Action - 索引操作指南(1) | 下一篇:WEBUS2.0 In Action - 搜索操作指南(1) 3. 添加.删除.撤销删除和修改文档 在WEBUS中要将 ...

  5. WEBUS2.0 In Action - [源代码] - C#代码搜索器

    最近由于工作的需要, 要分析大量C#代码, 在数万个cs文件中搜索特定关键词. 这是一项非常耗时的工作, 用Notepad++要运行接近半个小时. 于是我利用WEBUS2.0 SDK创建了一个代码搜索 ...

  6. 第二篇——Struts2的Action搜索顺序

    Struts2的Action的搜索顺序: 地址:http://localhost:8080/path1/path2/student.action     1.判断package是否存在,例如:/pat ...

  7. Struts2学习三----------Action搜索顺序

    © 版权声明:本文为博主原创文章,转载请注明出处 Struts2的Action的搜索顺序 http://localhost:8080/path1/path2/student.action 1)判断pa ...

  8. Struts2.0 去掉action后缀名

    刚刚接触Struts2.0,发现默认请求都会带着后缀名:action 就如下图,url地址中会暴露login.action(请原谅struts拼写错误..) 作为一个URL简洁爱(chu)好(nv)者 ...

  9. 帝国cms7.0修改默认搜索模版中的分页[!--show.page--]

    修改默认搜索模版的分页是在e/class/connect.php下 搜索下function page1就是我们要修改的分页了 下面贴上我修改后的分页 //前台分页 function page1($nu ...

随机推荐

  1. photosop快速对白色背景图片进行抠图

    因为其中有个作业,做个图书馆的小网页.所以打算取图书馆logo上面那几个字. 图片如下: 因为是白色背景,一开始打算使用魔棒工具,不过效果不好. 后来百度了下,使用色彩范围可以快速抠图 打开photo ...

  2. js对象小结

    前奏 对象是js的基本数据类型,准确来说除了字符串,数字,boolean值,null与undifine之外,js中的值都是对象.js中的对象是一种复合值,他将很多值(原始值或其他对象)聚合在一起,可以 ...

  3. Javascript 数组循环遍历之forEach

    1.  js 数组循环遍历. 数组循环变量,最先想到的就是 for(var i=0;i<count;i++)这样的方式了. 除此之外,也可以使用较简便的forEach 方式   2.  forE ...

  4. Windows X64 Patch Guard

    先简单介绍下PatchGuard ,摘自百度百科 PatchGuard就是Windows Vista的内核保护系统,防止任何非授权软件试图“修改”Windows内核,也就是说,Vista内核的新型金钟 ...

  5. webmatrix

    http://www.microsoft.com/web/webmatrix/ WebMatrix is a free, lightweight, cloud-connected web develo ...

  6. lintcode:线段树的查询

    线段树的查询 对于一个有n个数的整数数组,在对应的线段树中, 根节点所代表的区间为0-n-1, 每个节点有一个额外的属性max,值为该节点所代表的数组区间start到end内的最大值. 为Segmen ...

  7. 有N个大小不等的自然数(1--N),请将它们由小到大排序。要求程序算法:时间复杂度为O(n),空间复杂度为O(1)。

    #include<stdio.h> int main() { ]={,,,,,,,,}; int i,tmp; ;i<;i++) { ) { tmp=a[i]; a[i]=a[a[i ...

  8. JAVA编译异常处理:java.lang.OutOfMemoryError: PermGen space

    在Intellij开发工具中编译JAVA项目,出现以下错误: 六月 21, 2016 6:28:07 下午 org.apache.tomcat.util.modeler.BaseModelMBean ...

  9. Find K most Frequent items in array

    给定一个String数组,求K个出现最频繁的数. 记录一下查到的资料和思路: 1. 使用heap sorting, 先用hashmap求出单词和词频.需要额外建立一个class Node,把单词和词频 ...

  10. Linux内核通杀提权漏洞CVE-2016-5195验证

    一.漏洞简介 CVE-2016-5195这个漏洞是linux内核级的本地提权漏洞,原理是linux内核内存子系统在 处理私有只读存储映射的写入时复制机制发现了一个冲突条件.这个漏洞官方给出的影响范围是 ...