搜索引擎
jollyjumper
一点记录
展开
-
Lucene 6.6.0 BKD树
相关接口使用可以看TestBKD.java。仔细读BKDReader,BKD树是一颗完全二叉树,每个节点在一个维度上进行划分.发现里面为了节约空间做了很多差量编码工作.其中的PackedIndexTree结构是这样的:要知道这个结构是为了遍历树的,因此有pushLeft,pushRight,pop等操作,这里splitValuesStack可以看到冗余存了numDims维数据,但实...原创 2019-02-18 23:48:01 · 2045 阅读 · 0 评论 -
Lucene41中的PackedInts
ackedInts中提供了两种format,一个是Packed,可按long或字节对齐,另一个是PACKED_SINGLE_BLOCK.可以按照不同overheadRatio来选择对应FormatAndBits,调用fastestFormatAndBits就可以。另外这个文件提供了ecoder,Encoder,Reader,ReaderIterator,Mutable等接口。实现了Muta原创 2014-09-21 17:44:49 · 1309 阅读 · 0 评论 -
Lucene41PostingWriter源码分析
原来看lucene4.0的posting格式(http://blog.csdn.net/jollyjumper/article/details/30017581),发现这还是比较简单的VInt格式,据说VInt压缩解压都不错(medium),但解压时分支太多打乱CPU流水线因而不够高效,流行的索引压缩有很多,for,simple9,simple16,PForDelta是比较流行的一种,发现luce原创 2014-06-15 22:55:11 · 1457 阅读 · 0 评论 -
Lucene40PostingWriter
控制freq和prox两个文件的输出,比较简单。默认的skip interval是16,max skip level是10.由源码看出还是使用的VInt编码(而不是传说中快速的PForDelta)。存文档时docid列表的delta,如果不存文档频率,是一个delta,存的话如果是1则是(delta 存位置也类似,不过position是看是否存payload,payloadleng原创 2014-06-11 07:42:14 · 1194 阅读 · 0 评论 -
Lucene40SkipListWriter
多级跳跃表是保存在tim文件中的。tip是term index,tim是term dictionary。记忆方法是,p是pointer因此是term index。这个类会保存多个level的last变量和cur变量,同时使用RAMOutputStream数组缓存不同级别跳跃表的内容,一个term的所有doc添加完后才写入tim文件。几个主要方法:resetSkip:几个last变量重置原创 2014-06-12 08:19:40 · 1141 阅读 · 0 评论 -
转一篇不错的介绍Lucene4 FST的文章
http://download.csdn.net/download/guanxinquan/7380591http://blog.sina.com.cn/s/blog_616e189f0101fxxq.html原创 2014-05-24 21:17:20 · 3183 阅读 · 0 评论 -
IndexWriter.addIndexes解析
SegmentInfo包含除了delCount和delGen之外的段其他信息SegmentInfoPerCommit既包含SegmentInfo,也包含delCount和delGen信息。SegmentInfos是SegmentInfoPerCommit的集合,此外还包含counter,generation,user data信息。addIndexes(Directory...)操作过原创 2014-07-17 20:59:16 · 2014 阅读 · 1 评论 -
IndexReader关闭的问题
实时搜索设计开发中,IndexReader在饮用计数变为0时调用doClose,而SegmentReader则有一个addCoreClosedListener方法控制在SegmentCoreReaders关闭时的操作,搜索Lucene的代码只有在FieldCacheImpl中看到调用,其中的回调>是让SegmentCoreReaders关闭之后从field cache中删除field cache。原创 2014-07-17 20:57:10 · 2725 阅读 · 1 评论 -
圈图的geo query处理解决方案
一般的geo query是在一个点找附近多少米,几公里的poi点,现在有个产品可以在地图上圈一块地方找其中的poi点,“一块”其实是用户鼠标或触屏经过的点组成的多边形(可凹可凸)。目前的做法是找出x,y的最大最小四个坐标,这样构成一个矩形,但矩形不方便直接拿geo hash的grids, 所以取最长边,放大成一个矩形,再取它占用的grids,这样几个termquery最后再加个过滤操作。感觉上原创 2014-04-13 09:45:06 · 1569 阅读 · 0 评论 -
Lucene中Filter的性能问题
缘起于对geo filter的优化(http://blog.csdn.net/jollyjumper/article/details/23120197),当时模仿lucene的filter写了一个geo filter,其中getDocIdSet返回的时一个FixedSizeBitSet对象,在小的索引(1G)上测试出来性能比之前有明显提升,但在大的索引(23G)上反而比原来更慢。于是改成自己实现一原创 2014-04-13 08:56:38 · 1887 阅读 · 0 评论 -
GPU方法做倒排压缩和交集计算
之前一直想读这篇,今天读了一下,颇有收获:1.对文档按相似term聚类之后,delta较小,可以提高压缩率(similarity graph)1.GPU一般可以有几百个核,有shared memory和global memory,shared memory相当于寄存器的速度,global memory速度较慢2.有序数组上的搜索算法除了binary search还有interplati原创 2014-09-17 23:32:12 · 1558 阅读 · 0 评论 -
PForDelta的介绍论文
ttp://paperhub.s3.amazonaws.com/7558905a56f370848a04fa349dd8bb9d.pdfFOR(Frame-Of-Reference),PFor(Patched Frame-Of-Referene),cpu优化的guide line:1.减少control hazard,这个影响最大,cpu带分支预测功能在条件测试之前就先走,发现有错原创 2014-10-18 22:02:37 · 1775 阅读 · 0 评论 -
DAT的实现
手痒,自己实现了一下,UT已经通过。在lucene4基础上实现,加上接口不到300行代码。package com.dp.junhao.jhsegmenter;import gnu.trove.iterator.TByteIterator;import gnu.trove.list.array.TByteArrayList;import gnu.trove.procedure.TBytePr原创 2017-08-11 22:48:42 · 798 阅读 · 0 评论 -
Lucene 4.0 FrozenBufferedDeletes
其实存储的内容基本跟BufferedDeletes一样,只不过因为不需要修改了,所以存储更紧凑一点,多数成员是final。具体是:PrefixCodedTerms terms;int termCount;Query[] queries;int[] queryLimits;int bytesUsed;int numDeletes;long gen;PrefixCo原创 2016-08-06 01:02:54 · 292 阅读 · 0 评论 -
Lucene 4.0 DocumentsWriterDeleteQueue
里面是一个非阻塞队列,仅保存尾巴(头在globalDeleteSlice中保存),外加一个BufferedDeletes。每次删除之后都会调tryApplyGlobalSlice将队列中的内容apply到BufferedDeletes中,从而清空全局队列,newSlice之后的队列是调用方自己维护。这里还有一个很潮的AtomicReferenceFieldUpdater用于原子更新对象中的原创 2016-08-06 00:48:51 · 689 阅读 · 1 评论 -
Lucene4.0 BufferedDeletes
缓存一个segment要删除的Term,Query或docId,一旦需要flush,则转换为FrozenDeletes。主要的数据成员:Map terms // 要删除的term和docIDUpto映射AtomicInteger numDeletes // 删除的term数量,注意不是terms.size(),重复的term多次累加Map queries // 要删除的que原创 2016-08-06 00:19:44 · 273 阅读 · 0 评论 -
索引截断技术
搜索有的关键词时返回可能会到数十万,但实际上只返回排序靠前的几百条,而参与排序的商户到只要到10万一般结果不会偏差太大。可以给每个商户在索引阶段分配一个静态分,search时只返回静态分top 10万个。有两种实现方法:1.索引时每个段刷出去时docId按静态分降序排(merge时也需要相同处理),结果召回时各个段中取top就可以保证不会取到倒排链中靠后的文档,对返回结果较小的请求也有一点原创 2014-12-06 11:32:24 · 1766 阅读 · 0 评论 -
一种减少索引下载/切换总时间的技巧
现在商户索引下载时14台searcher机器同时下载索引大概要花10-12分钟,然后一组一组(3个分布式锁,5组)切换。假定warmup时间为1分半,所以下载+切换的总时间=10分钟 + 5 * 1.5分钟 = 17.5分钟。注意到这里3台机器切换时,剩下的机器既不切换也不下载,如果能利用切换时间也做下载,将会省下多组切换时间,最理想是只花费1组切换时间,总时间为10分钟 + 1.5分原创 2014-12-06 09:14:47 · 1117 阅读 · 0 评论 -
Facebook图搜索unicorn
unicorn(独角兽),里面类似于倒排链的reference list,对应的term如friend:2,表示entity 2的朋友列表,整个结构是shard的,上面是top aggregator,然后是rack aggreator,支持StrongOr,weakAnd,Difference操作,还有apply(如找朋友的朋友),extract,有个nosql图数据库neo4j也是类似的,只是听原创 2014-10-18 21:50:01 · 1483 阅读 · 0 评论 -
LuceneIndexFileDeleter会保留初始的commit
给实时索引添加了merge策略,持续更新时发现有做merge,但索引目录中的段数远远大于RealTimeIndexWriter中的段数,就是有些merge的段应该删除,目录中没有删除。而关闭searcher之后索引目录就变小了,段数也对了。定位之后发现IndexFileDeleter构造函数中有个checkpoint(segmentInfos,false),false会将第一个commit加入原创 2014-10-18 22:04:51 · 1148 阅读 · 0 评论 -
Lucene段合并的参数估计
使用lucene默认的TieredMergePolicy,索引更新时最大会占用多少硬盘,要看mergepolicy何时触发merge。从代码中可以看出,只有当eligible.size() >= allowedSegCountInt时才触发。eligible是大小不超过阈值的段集合,allowedSegCountInt计算如下,设segsPerTier为a,maxMergeAtOnce为b原创 2014-10-18 21:56:16 · 1905 阅读 · 0 评论 -
Lucene新版本对ConjunctionScorer的优化
Lucene 4.0版本的DocIdSetIterator中没有cost方法,而4.7.0则有这个方法,表示遍历整个DocIdSet的代价,对于DocsEnum就是其长度了,对于Scorer就可以是符合查询的个数了。ConjunctionScorer可以取其中cost最小的那个scorer,做and操作,而4.0中则是猜测,认为第一个doc最大的那个应该最稀疏,从那个scorer开始做。原创 2014-04-27 18:11:25 · 1216 阅读 · 0 评论 -
关于使用Filter减少Lucene tf idf打分计算的调研
将query改成filter,lucene中有个QueryWrapperFilter性能比较差,所以基本上都需要自己写filter,包括TermFilter,ExactPhraseFilter,ConjunctionFilter,DisjunctionFilter。这几天验证下来,还是or改善最明显,4个termfilter,4508个返回结果,在我本机上性能提高1/3。ExactPhrase原创 2014-04-27 15:48:43 · 2009 阅读 · 0 评论 -
建索引时优化的观察和思考
同事调整了IndexWriterConfig的maxThreadStates参数,发现性能有很大提升,原来之前一直没去注意这个东西。addDocument时默认会调用ThreadAffinityDocumentsWriterThreadPool来获取线程锁,而这个线程池默认是8个线程,如果同时addDocument的线程多于8个,则线程处在等待锁的状态(一般是等最小竞争的>锁),所以本质上原创 2014-05-09 22:04:42 · 1114 阅读 · 0 评论 -
Lucene 4.0 TieredMergePolicy
默认的merge policy。findMerges:先将所有段按照扣除删除文档之后的字节数(bytesize * (1.0 - delRatio))降序排,对其中size() > 2.5G(maxMergedSegmentSize / 2)的段排除在外,其他只要不是正在归并的段,加入候选。这个候选的列表如果大于allowedSegCount(allowedSegCount计算方法如下原创 2014-04-30 13:46:10 · 2007 阅读 · 0 评论 -
Lucene Index Format 笔记
原文在这里:http://hackerlabs.org/blog/2011/10/01/hacking-lucene-the-index-format/这篇文章很不错,把lucene index格式都列出来了.几个文件如下:fnm => Field Informationfdx => Field index Field数据索引fdt => Field Data Field数据t原创 2014-02-18 22:18:52 · 1567 阅读 · 0 评论 -
空间索引技术(Spatial Index)
Lucene(contrib包)和mongodb中提供了一种空间索引,实际上就是对经纬度二维坐标进行编码之后仍使用trie树索引,对于检索一个点附近多少距离(比如5公里)之内的点,不需要遍历所有文档,只需要找grid点离该位置grid点5公里以内的所有文档就可以了.原创 2014-01-20 13:42:08 · 4853 阅读 · 0 评论 -
An Efficient Digital Search Algorithm by Using a Double-Array Structure笔记
双数组trie树实现的第一篇论文,日本人JUN-ICHI AOE 1989年撰写的.大概看完,简单记录下,可能有不准确的地方.trie树有静态和动态两种,静态的直接就是一个DFA,没什么好说的,使用内存什么都比较确定而且最少.动态的可以支持删除和插入,双数组做法就是一种实现.为了保证字典中所有词都不是其他词的前缀,在每个词后面加上#标识.双数组是指base和check这两个数组,bas原创 2014-01-20 19:15:47 · 1636 阅读 · 0 评论 -
solr使用的一点记录
对pubmed 3200多万篇,总计64G的医学文献摘要数据进行索引,索引了大约6个小时,索引之后发现还有18G,发现搜索是支持phrase query的,但是不需要高亮(因为文本数据不store在solr上而在cabinet上),text的定义中加上了termPositions=false,明天看看索引会不会小一点.原创 2014-01-20 18:54:59 · 1386 阅读 · 0 评论 -
Lucene中的highlighter
Lucence中的highlighter除了高亮关键词之外还有动态摘要的功能,动态摘要就是将文本分成若干片段(fragment),选取一个或多个与查询最相关(scorer计算)的片段.有的论文中选取段时是从查询词所在位置向左右扩充选取,并且据一般习惯用户更多注意一段话的起始部分,一般是从一个语句的开始超过一定长度可以抛弃后面的部分而不是前面.FastVectorHighlighter效率较高,原创 2014-01-16 22:12:15 · 2244 阅读 · 0 评论 -
Boilerplate Detection Using Shallow Text Features论文小笔记
网页正文抽取是个很重要的东西,可以减少索引大小,让搜索结果更准确,数据挖掘也更准确.昨天晚上在网上看到这个东西:http://code.google.com/p/boilerpipe/很高兴,用于抽取网页上的正文,它还有一个gae的页面:http://boilerpipe-web.appspot.com,测了一下准确率,召回率都还没蛮高的.最关键的一点是:几年前在一家小公司我也做过原创 2014-01-24 23:39:15 · 1826 阅读 · 0 评论 -
尝试更新了下suggest索引
suggest部分比较简单,只给出相应的PrefixQuery查询,拿出相应的条目,schema.xml中只有两个字段: id id对应更新的是主题词和对应影响因子的csv文件:curl http://192.168.1.21:8983/solr/suggest/update/csv?commit=true --data-binary @en_sug原创 2014-01-17 12:57:45 · 1305 阅读 · 0 评论 -
朴素贝叶斯经典案例:语言识别(language detection)
我对语言识别的问题一直很感兴趣,记得10年做全网爬虫时同事写了一个简单的网页语言检测,比较简单,只是判断unicode code point是否有足够数量落在中文的code point上,连基本的html标签都没有去除,当时也没有测试效果,很可能会把日本,韩文网页也当做中文页面了.最近学习solr/lucene,里面就带有language detection功能,可以使用两个库,一个是tika原创 2014-01-22 23:19:03 · 4734 阅读 · 1 评论 -
使用多线程压缩提高全量索引切换速度
目前全量索引约22G,花费约1个小时的时间,indexer做完之后放在ftp,searcher同时下载,下载完成之后切换索引,切换索引本身只花费1分钟左右的warmup时间,但下载由于机房带宽总共250M的限制(12台searcher),需要大约20分钟的时间。使用gzip对索引压缩就要花费22分钟时间,而使用ftp z mode压缩,本身也是调用单线程zlib,不会比22分钟更快。看到一个smp原创 2014-03-30 00:40:27 · 1595 阅读 · 0 评论 -
Lucene TFIDFSimilarity
读了Lucene打分文档之后,有必要了解一下TFIDFSimilarity中的调用堆栈。public abstract class TFIDFSimilarity extends Similarity { public TFIDFSimilarity() {} @Override // overlap overlap原创 2014-04-20 22:38:06 · 2770 阅读 · 0 评论 -
Zoie Merge Policy
Zoie中有个ZoieMergePolicy应该价值不大,这是针对lucene早期版本中merge时不考虑删除的doc占比而做的改进,和LogMergePolicy一样也是只做相邻段的合并,合并时使用原创 2014-05-09 21:47:02 · 975 阅读 · 0 评论 -
Lucene4.0 LogMergePolicy
其特点是给定的段列表顺序归并,不像TieredMergePolicy那样按大小排序之后决定。norm = log(10),levelFloor=log(minMergeSize)/norm,对段列表中的元素,添加level值为log(size)/norm(即使log 10 size)的seg。从列表位置0开始,取最大的logLevel为maxLevel,levelBottom=(float原创 2014-05-09 21:45:59 · 1740 阅读 · 0 评论 -
BooleanScorer和BooleanScorer2的差别
几个termquery or起来(全部and起来用ConjunctionScorer),如果collector acceptOutOfOrder返回true,默认使用BooleanScorer,它按照2048一个窗口一个窗口地计算分数,由于nextDocID没有顺序要求,速度较快。如果collector acceptOutOfOrder返回false,则使用BooleanScorer2,归并链表时原创 2014-04-08 13:36:46 · 1814 阅读 · 0 评论 -
关于numa
服务器是numa架构的,有两个node,经测试加入numactl --interleave启动searcher并没有加速。关于numa,淘宝莫枢的slides: http://www.slideshare.net/RednaxelaFX/usenuma-on-jdk6linux指出仅UseParallelGC,UseParallelOldGC可以配合-X:+UseNUMA,可以提高性能(e原创 2014-04-22 21:34:41 · 2120 阅读 · 0 评论 -
记Lucene GEO Query的一点优化
目前我们使用的是Lucene 4.0,上面对GEO query的使用是这样的,索引阶段使用geo hash索引多个级别的geo grid,检索阶段获取geo grid做termquery,or起来,最后search之后在collector中按照距离做一次手动的过滤,这样做不方便的是geo query不能任意和其他query做or组合。又查看了lucene spatial中的实现,是直接确定精度原创 2014-04-07 18:05:33 · 2433 阅读 · 0 评论