搜索引擎Lucene(7):索引性能优化

1、性能调优

1.1、索引-搜索时延调优

索引一搜索时延是指从添加、更新或删除索引中的文档开始,直到用户在搜索中看见上述操作结果之间的时间跨度。对于很多应用程序来说,该性能指标是很重要的。但由于 Reader 通常只在被打开时的“特定时间”来展现索引,所以减少索引-搜索时延的唯一方法就是在程序中多次重新开启 Reader 。

所幸的是, Luccne中的近实时搜索功能会将这个转换时间维持在最小值,在实际使用中通常为几十毫秒。在使用Indexwriter 完成索引修改后,你可以通过调用Indexwriter . getReader ( )方法或者调用之前那个IndexReader 的reopen ( )方法来重新打开一个 Reader 。但若这个操作若太频繁则会降低索引吞吐量,因为每次操作时,Indexwriter 都会将缓存中的数据写人磁盘。下面是一些关于减少转换时间的建议:

  • 通过使用IndexWriter.setMergedSegmentWarmer使IndexWriter在新合并的段被搜索前激活它。在激活过程中,新的近实时Reader会保持打开状态并使用合并前的段。这在大段合并中尤其重要,它会减少后续针对近实时Reader的新搜索的时延。
  • 尝试将IndexWriter类转换成BalanceMergePolicy类,后者可以在各个捐赠模块中获取。该MergePolicy类被设计用来减少段合并操作,因为该操作会消耗大量CPU和I/O资源,从而对搜索性能带来不利的影响。
  • 可能的话,将IndexWriter的MaxBufferDocs参数设小点。这样即使不重新打开近实时Reader,系统也会刷新小的段。尽管这会减少净索引率,但它实际上会重新开启Reader的周七保持为最小值。
  • 如果只向索引添加文档,那一定要使用addDocument方法而不是updateDocument方法,因为使用updateDocument方法会增加系统开销,即使指定某个项也不会删除任何文档:IndexWriter在创建新的近实时Reader时必须搜索每个被删除的项。

1.2、索引操作吞吐量调优

索引吞吐量主要用来衡量每秒钟编入索引的文档数量,该性能值取决于建立和更新索引的操作时耗。提高查询索引吞吐量的方案:

  • 使用多线程。使用IndexWriter内置的多线程;
  • 设置触发IndexWriter刷新的事件,将其设置为通过内存使用量来刷新,而不是靠文档计数来刷新。
  • 关掉复制文件格式选项(IndexWriter.setUseCompoundFile(false))。在索引期间若使用复杂文件格式会消耗一些处理事件。采用该方案程序会在搜索期间有一个小的性能提升。但这个方案需要多得多的文件描述符用于reader打开他们,因此你可以减小mergeFactor值以避免达到文件描述符数量上限。关闭复杂文件格式选项可以同设置compound=false实现。
  • 对Document示例和Field实例进行重用。如果你要处理的文档时高度规则的,那么可以创建单个Document实例,并用它来容纳Field实例。这里只需要根据情况来修改Field值,然后调用同一Documents实例的addDocument方法即可。
  • 针对不同的mergeFactor值进行测试。更高的值意味着索引期间更低的段合并开销,但同时也意味着更慢的搜索速度,因为此时的索引通常会包含更多的段。如果该值设置的过高,并同时关闭了compound选项,则程序可能会达到操作系统的文件描述符上限。段合并操作是在索引期间后台程序自动完成的,较高的mergeFactor值能获得更高的索引性能。但若在最后进行索引优化,那么较低的mergeFactor值会带来更快的优化速度,因为在索引操作期间程序会利用并发机制完成段合并操作。故建议对程序分别进行高低多种值的测试,利用计算机的实际性能来告诉你最优值。
  • 谨慎使用optimize()方法,最好是使用optimize(maxNumSegments)方法来代替。改方法会将索引所包含的最大段数据优化至maxNumSegments值,这可以大量减少索引优化开销,同时也能较大地提高搜索速度。
  • 将文档索引到各个分离的索引中,或者有可能是位于不同计算机上的各个分离索引中,然后调用IndexWriter.addIndexesNoOptimize方法来合并这些索引。不要使用较早的addIndexs方法,它经常额外且不必要地调用Optimize()方法。
  • 对文档创建速度和文档语汇单元化速度进行测试,方法是在你的算法中使用ReadTokens任务。该任务会逐个访问文档中每个域,并使用指定的分析器对它们进行语汇单元化操作。

1.3、搜索相关调优

提升性能的方法及步骤:

  • 通过调用IndexReader.open(dir)或者IndexReader.open(dir,true)方法以只读的方式使用IndexReader。以只读方式使用IndexReader能得到更好的并发运行效果,因为这种调用方式可以避免一些针对内部数据结构的同步处理。当打开IndexReader时,系统默认的处理方式是只读的。
  • 如果应用程序未运行在Windows平台上,那么请使用NioFsDirectory,这能比FsDirectory带来更好的并发运行效果。如果应用程序运行在64位JVM上,可以使用MMapDirectory。
  • 减少用户和Lucene之间的每步操作中不必要的时延。例如:要确保供多个线程共同访问的搜索请求队列是先进先出的,以使搜索结果按照搜索请求的排队顺序返回。同时还有确保Lucene返回搜索的结果速度要快。
  • 确保时延足够多的线程来充分利用计算机的硬件资源。在吞吐量持续增加的情况下要继续增加线程数,直到吞吐量不再增加位置,但也不能增加太多线程以至于搜索时延越来越恶化。这里我们要找到该临界点。
  • 在实际运行程序前对它们进行激活。因为首次使用某个排序时,必须将相关的域写入FieldCache对象中。预处理可以通过为可能参与排序的域进行一次搜索处理来实现。
  • 如果使用RAM.FieldCache将所有被保存的域写入RAM的话,推荐使用FieldCache而不是直接使用被保存的域,因为后者必须针对每个文档而被写入磁盘。将域写入FieldCache对象的过程比较消耗系统资源,但该操作只在首次访问时针对每个域进行一次,一旦将域写入FieldCache对象,后续对它的访问就非常快,只有操作系统不针对JVM的内存进行换页操作。
  • 减少对mergeFactor的使用,以使索引中保存较少的段。
  • 关闭使用索引的复合文件格式。
  • 限制使用向量,业务检索他们的过程会很慢。如果必须使用向量的话,只需在搜索中使用它们。可以使用TermVectorMapper类仔细挑选那些需要使用向量的搜索。
  • 如果必须加装被存储的域,可以使用FieldSector类将域限制在需要加载的范围内,对较大的域来说,可以使用延迟加载方式,这样就只在需要的时候才能加载域的内容。
  • 针对索引周期性运行optimize或者optimize(maxNumSegments)方法进行优化。
  • 搜索结果条数要根据需要来设定。
  • 只在必要情况下重新打开IndexReader类。
  • 调用query.rewrite().toString()方法打印搜索结果。这是lucene实际运行的搜索方式。
  • 如果程序要使用FuzzyQuery类,请将最小前缀长度设置成大于0.这样才能在实际运行时增加minimumSimilarity值。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容