为什么说Lucene不好
在Lingway公司,我們使用了Lucene至進(jìn)今已有好幾年時(shí)間。對(duì)那些剛接觸Lucene的人來說,這里是使用它的關(guān)鍵:Apache Lucene是一個(gè)由java編寫的高性能,全方位的單詞搜索引擎庫。
?
在批評(píng)它之前,我必須承認(rèn)Lucene是一個(gè)高性能的劃詞搜索引擎。幾年來,Lucene已經(jīng)被看作是用java編寫的嵌入式搜索引擎中的一等公民。它的聲譽(yù)每日劇增,并且仍然是開源java搜索引擎中的最佳。每個(gè)人都在說:“Doug Cutting做了一項(xiàng)偉大的工作”。然而,最近的幾個(gè)月內(nèi),開發(fā)的進(jìn)程變得緩慢,我認(rèn)為Lucene將不會(huì)滿足現(xiàn)代的文檔處理需求。不要把東西搞糟:我不是搜索引擎開發(fā)者,我只是個(gè)開發(fā)者,使用搜索引擎,來提供合適信息的檢索科技。
?
這貼是討論為什么對(duì)未來的開發(fā)者而言,Lucene不是最好選擇,至少對(duì)我們而言如此,并且情況并沒有得到改變。我們列出Lucene的局限性:Lingway公司基于語意來生成復(fù)雜的查詢。例如當(dāng)你正在查找關(guān)于“中東地區(qū)沖突”的文章,你也許還需要找關(guān)于“伊拉克戰(zhàn)爭”文章。在上面這個(gè)用例中,“戰(zhàn)爭”和“伊拉克”分別是“沖突”和“中東”的擴(kuò)展。我們使用一種技術(shù)能分析你的查詢,產(chǎn)生相應(yīng)的最合適的擴(kuò)展,為它們生成查詢。然而,為了得到相關(guān)的結(jié)果,這些還是不夠的:通過Lucene實(shí)現(xiàn)的類似Google的等級(jí)或是經(jīng)常變化積分的并不能滿足語意級(jí)別積分。例如,一個(gè)包含“中”和“東”短語,但是被超過一個(gè)以上的單詞隔開,這種情況并不是我們想要查找的。更重要的是,相對(duì)常規(guī)的單詞,我們應(yīng)該給擴(kuò)展更低的分?jǐn)?shù)。比如,我們應(yīng)該給“中東地區(qū)沖突”這個(gè)短語更高的分?jǐn)?shù),而不是“伊拉克戰(zhàn)爭”。
?
在Lingway公司,我們認(rèn)為這種文章相關(guān)性技術(shù)是一種未來的搜索引擎。Google在文章搜索上做的很出色。但我們想要的卻是最相關(guān)的文章。但是,大部分的當(dāng)代搜索引擎都沒有對(duì)這樣復(fù)雜查詢做相關(guān)的設(shè)計(jì)…Lucene被wikipedia使用,如果你注意到當(dāng)你查詢查過一個(gè)單詞時(shí),大多數(shù)的查詢結(jié)果并不是由關(guān)聯(lián)的…
?
為了演示需求,這里有一個(gè)Lingway公司即將上線的KM3.7產(chǎn)品的界面截圖。這里我們用法語寫一個(gè)查詢,用來查找那些同樣主題,而用英語寫的文章。注意,這可不僅僅是簡簡單單的翻譯,我們稱之為語言交叉模式:
?
注意到那些綠色的匹配:chanteur變成了singer,但是我們也發(fā)現(xiàn)singing被匹配了。同樣情況流行樂成為藍(lán)調(diào)的擴(kuò)展。
?
6大理由不選用Lucene
6. 沒有對(duì)集群的內(nèi)置支持。
如果你創(chuàng)建集群,你可以寫出自己對(duì)Directory的實(shí)現(xiàn),或是使用Solr或者使用Nutch+Hadoop。Solr和Nutch都支持Lucene,但不是直接的替代。Lucene是可嵌入的,而你必須支持Solr和Nutch..我認(rèn)為Hadoop從Lucene團(tuán)隊(duì)中產(chǎn)生并不驚訝:Lucene并不是通用的。它的內(nèi)在性決定了對(duì)大多數(shù)場合來說它是非常快速的,但是對(duì)大型文檔集合時(shí),你不得不排除Lucene。因?yàn)樗趦?nèi)核級(jí)別上并沒有實(shí)現(xiàn)集群,你必須把Lucene轉(zhuǎn)換到別的搜索引擎,這樣做并不直接。轉(zhuǎn)換到Solr或者Nutch上的問題會(huì)讓你遇到許多不必要的麻煩:Nutch中的集成crawling和Solr中的檢索服務(wù)。
?
5.跨度查詢太慢
這對(duì)Lingway公司來說可能是個(gè)特殊的問題。我們對(duì)跨度查詢有很強(qiáng)要求,Lucene檢索結(jié)構(gòu)已經(jīng)開始添加這一細(xì)節(jié),但它們當(dāng)初可沒這么想。最基礎(chǔ)的實(shí)現(xiàn)導(dǎo)致了復(fù)雜的算法并且運(yùn)行緩慢,尤其是當(dāng)某些短語在一份文檔中重復(fù)了許多次出現(xiàn)。這是為什么我傾向說Lucene是一個(gè)高性能的劃詞檢索引擎當(dāng)你僅僅使用基本的布爾查詢時(shí)。
?
4.積分不能被插件化
Lucene有自己對(duì)積分算法的實(shí)現(xiàn),當(dāng)條件增加時(shí)使用Similarity類。但很快它顯示出局限性當(dāng)你想要表示復(fù)雜的積分,例如基于實(shí)際匹配和元數(shù)據(jù)的查詢。如果你這樣做,你不得不繼承Lucene的查詢類。因?yàn)?/span>Lucene使用類似tf/idf的積分算法,然而在我們遇到的場合,在語意上的積分上Lucene的積分機(jī)制并不合適。我們被迫重寫每一個(gè)Lucene的查詢類使得它支持我們自定義的積分。這是一個(gè)問題。
?
3.Lucene并非良好設(shè)計(jì)
作為一個(gè)系統(tǒng)架構(gòu)師,我傾向認(rèn)為(1)Lucene有一個(gè)非常糟糕的OO設(shè)計(jì)。雖然有包,有類的設(shè)計(jì),但是它幾乎沒有任何設(shè)計(jì)模式。這讓我想起一個(gè)由C(++)開發(fā)者的行為,并且他把壞習(xí)慣帶到了java中。這造成了,當(dāng)你需要自定義Lucene來滿足你的需求(你將來必定會(huì)遇到這樣的需求),你必須面對(duì)這樣的問題。例如:
- <!--[if !supportLists]--> <!--[endif]-->幾乎沒有使用接口。查詢類(例如BooleanQuery,SpanQuery,TermQuery…)都是一個(gè)抽象類的子類。如果你要添加其中的一個(gè)細(xì)節(jié),你會(huì)首先想到寫一個(gè)接口來描述你擴(kuò)展的契約,但是抽象的Query類并沒有實(shí)現(xiàn)接口,你必須經(jīng)常的變化自己的查詢對(duì)象到Query中并在本地Lucene中調(diào)用。成堆的例子如(HitCollecor,…)這對(duì)使用AOP和自動(dòng)代理來說也是一個(gè)問題.
- <!--[if !supportLists]--> <!--[endif]-->別扭的迭代實(shí)現(xiàn).沒有hasNext()方法,next()方法返回布爾類型并刷新對(duì)象內(nèi)容.這對(duì)你想要保持對(duì)迭代的元素跟蹤來說非常的痛苦.我假定這是故意用來節(jié)省內(nèi)存但是它又一次導(dǎo)致了算法上的雜亂和復(fù)雜.
?
2.一個(gè)關(guān)閉的API使得繼承Lucene成為痛苦
在Lucene的世界中,它被稱之為特性。當(dāng)某些用戶需要得到某些細(xì)節(jié),方針是開放類。這導(dǎo)致了大多數(shù)的類都是包保護(hù)級(jí)別的,這意味著你不能夠繼承他們(除非在你創(chuàng)建的類似在同一個(gè)包下,這樣做會(huì)污染客戶代碼)或者你不得不復(fù)制和重寫代碼。更重要的是,如同上面一點(diǎn)提到的,這個(gè)嚴(yán)重缺乏OO設(shè)計(jì)的結(jié)構(gòu),一些類應(yīng)該被設(shè)為內(nèi)部類卻沒有,匿名類被用作復(fù)雜的計(jì)算當(dāng)你需要重寫他們的行為。關(guān)閉API的理由是讓代碼在發(fā)布前變得整潔并且穩(wěn)定。雖然想法很光榮,但它再一次讓人感到痛苦。因?yàn)槿绻阌幸恍┐a和Lucene的主要思路并不吻合,你不得不經(jīng)常回歸Lucene的改進(jìn)到你自己的版本直到你的補(bǔ)丁被接受。
然而當(dāng)開發(fā)者開始越來越長的限制API的更改,你的補(bǔ)丁很少有機(jī)會(huì)被接受。在一些類和方法上加上final修飾符會(huì)讓你遇到問題。我認(rèn)為如果Spring框架有這樣的限制,是覺不會(huì)流行起來。
?
<!--[if !supportLists]-->1.?????? Lucene搜索算法不適合網(wǎng)格計(jì)算<!--[endif]-->
Lucene被寫出來的時(shí)候硬件還沒有很大的內(nèi)存,多處理器也不存在。因此,索引結(jié)構(gòu)是被設(shè)計(jì)成使用線性的內(nèi)存開銷很小的方式。我花了很長的時(shí)間來重寫跨度查詢算法,并使用多線程內(nèi)容(使用雙核處理器),但是基于迭代器的目錄讀取算法幾乎不能實(shí)現(xiàn)。在一些罕見的場合你能做一些優(yōu)化并能迭代一個(gè)索引通過并行方式,但是大多數(shù)場合這是不可能的。我們遇到的情況是,當(dāng)我們有一個(gè)復(fù)雜的,超過50+的內(nèi)嵌跨度查詢,CPU還在空閑但I/O卻一直忙碌,甚至在使用了RAMDirectory.
?
有沒有替代品?
我認(rèn)為最后一個(gè)觀點(diǎn)充滿疑問:Lucene到達(dá)了它的極限當(dāng)它在現(xiàn)在硬件基礎(chǔ)的條件下,檢索大型數(shù)據(jù)集合時(shí)。那就是我為什么尋找下一個(gè)可以替代Lucene的出現(xiàn)。在閱讀了博客目錄和 Wikia的討論后,我發(fā)現(xiàn)并沒有很多的替代品。然而我最后推薦一個(gè)有希望的方案:MG4J。它有一個(gè)良好的面向?qū)ο笤O(shè)計(jì),性能良好的檢索(索引比Lucene慢),內(nèi)存開銷上也很小,達(dá)到10倍于Lucene速度的跨度查詢,在我的跨度查詢基準(zhǔn)上,并且是原生上支持集群。同樣它也內(nèi)置了負(fù)載平衡,而Lucene最近才加入這項(xiàng)功能并且還是實(shí)驗(yàn)性質(zhì)的。然而MG4J仍然缺少一些特性例如簡單的索引指數(shù),文檔移除和更簡單的使用索引處理。讓我感到高興的是我可以自定義Lucene上的功能在MG4J上只需花幾個(gè)小時(shí),而在Lucene上卻需要數(shù)天。
?
我認(rèn)為對(duì)開源的搜索引擎來說仍然有發(fā)展空間,它不是通過單臺(tái)電腦用有限的內(nèi)存來索引批量文檔,而是通過透明的分布式索引來提供對(duì)大型數(shù)據(jù)集合檢索更為快捷的答案。你不必利用應(yīng)用來獲得集群特性。Lucene對(duì)第一類搜索引擎有了很好的實(shí)現(xiàn),單我認(rèn)為它并不符合我們的需求:在一個(gè)合理的時(shí)間內(nèi)找到最佳的答案。基于tf/idf的搜索算法和google的等級(jí)并不是未來搜索引擎的趨勢(shì)。實(shí)現(xiàn)對(duì)原數(shù)據(jù)和語義的復(fù)雜查詢并找出相關(guān)的信息,這是Lingway公司(通過Lucene和其他搜索引擎技術(shù))所作的,不過它要求有更多支持新硬件的新技術(shù)。
?
使用Lucene的一個(gè)好理由
無論我如何指責(zé)Lucene,它仍然是java開源解決方案中的最佳實(shí)現(xiàn)。
?
轉(zhuǎn)載于:https://www.cnblogs.com/zhangjunpo/articles/1336832.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的为什么说Lucene不好的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jsp cookie 中文乱码 的解决方
- 下一篇: struts2 获取 session