lucene4.7 分頁(五)

  咱們先來看下下面的問題,如今咱們的索引裏有2億多的數據,那麼如今的需求是,把索引裏的所有數據,讀取而後寫入txt文本里,對於這麼一個量級的數據,顯然是不可能一會兒所有讀取完的,那得要多大的內存纔可以支持下來,是一個很恐怖的內存量,因此就引入散仙今天要給你們介紹的一個功能,Lucene的分頁技術。 


介紹分頁以前,咱們先來看看上面的那個需求,不用分頁的解決辦法, 
其實在lucene裏面,每個索引都會對應一個不重複的docid,而這一點跟Oralce數據庫的僞列rownum同樣,偏偏正是因爲這個docid的存在,因此讓lucene在海量數據檢索時從而擁有更好的性能,咱們都知道Oracle數據庫在分頁時,使用的就是僞列進行分頁,那麼個人lucene也是同樣,既然有一個docid的存在,那麼上面的需求就很簡單了
 

方法一:依次根據每一個docid獲取文檔而後寫入txt中,這樣的以來,就避免了內存不足的缺點,可是這樣單條讀取的話,速度上可能會慢一點,但能知足需求無可厚非。僞代碼以下
java

    try{
        directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
        IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
        IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
        for(int i=0;i<reader.numDocs();i++){//numDocs可能很大
         Document doc=search.doc(i);//依次獲取每一個docid對應的Document
        //能夠在此部,作個批量操做,加快寫入速度
        }  
        
         reader.close();//關閉資源
         directory.close();//關閉鏈接
        
        }catch(Exception e){
            e.printStackTrace();
        }

Lucene的分頁,總的來講有兩種形式,總結以下圖表格。(若是存在不合適之處,歡迎指正!)
數據庫

編號 方式 優勢 缺點
1 在ScoresDocs裏進行分頁 無需再次查詢索引,速度很快 在海量數據時,會內存溢出
2 利用SearchAfter,再次查詢分頁 適合大批量數據的分頁 再次查詢,速度相對慢一點,但能夠利用緩存彌補
從上圖咱們能夠分析出,ScoreDocs適合在數據量不是很大的場景下進行分頁,而SearchAfter則都適合,因此,咱們要根據本身的業務需求,合理的選出適合本身的分頁方式。 

在咱們瞭解這2中分頁技術的優缺點以後,咱們再來探討下上面那個讀2億數據存入txt文本里,在這裏,SocreDocs不適合這種場景,固然若是你內存足夠大的話,能夠嘗試下,通用分頁分批讀取的方式,能夠提高咱們的寫入效率,效果是比單條單條讀取的速度是要快不少的。雖然ScoresDocs的分頁方式在本需求上不適合,可是做爲示例,下面散仙給出使用ScoreDocs進行分頁的代碼:

    try{
        directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
        IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
        IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
        
 
         TopDocs all=search.search(new MatchAllDocsQuery(), 50000);
         int offset=0;//起始位置
         int pageSize=30;//分頁的條數
         int total=30;//結束條數
         int z=0;
         while(z<=50){//總分頁數
         System.out.println("==============================");
         pageScoreDocs(offset,total,search, all.scoreDocs);//調用分頁打印
         offset=(z*pageSize+pageSize);//下一頁的位置增量
         z++;//分頁數+1;
             total=offset+pageSize;//下一次的結束分頁量
         }
         reader.close();//關閉資源
         directory.close();//關閉鏈接
        
        }catch(Exception e){
            e.printStackTrace();
        }
public void pageScoreDocs(int offset,int total,IndexSearcher searcher,ScoreDoc[] doc) throws Exception{
        //System.out.println("offset:"+offset+"===>"+total);
        for(int i=offset;i<total;i++){
            //System.out.println("i"+i+"==>"+doc.length);
            if(i>doc.length-1){//當分頁的長度數大於總數就中止
                
                break;
            }else{
        
               Document dosc=searcher.doc(doc[i].doc);
               System.out.println(dosc.get("name"));
           
            }
        }

最後咱們來看下使用SearcherAfter進行分頁的方式,代碼以下:
緩存

    try{
        directory=FSDirectory.open(new File(indexReadPath));//打開索引文件夾
        IndexReader  reader=DirectoryReader.open(directory);//讀取目錄
        IndexSearcher search=new IndexSearcher(reader);//初始化查詢組件
        
         int pageStart=0;
         ScoreDoc lastBottom=null;//至關於pageSize
         while(pageStart<10){//這個只有是paged.scoreDocs.length的倍數加一纔有可能翻頁操做
             TopDocs paged=null;
             paged=search.searchAfter(lastBottom, new MatchAllDocsQuery(),null,30);//查詢首次的30條
             if(paged.scoreDocs.length==0){
                 break;//若是下一頁的命中數爲0的狀況下,循環自動結束
             }
             page(search,paged);//分頁操做,此步是傳到方法裏對數據作處理的
             
             pageStart+=paged.scoreDocs.length;//下一次分頁總在上一次分頁的基礎上
             lastBottom=paged.scoreDocs[paged.scoreDocs.length-1];//上一次的總量-1,成爲下一次的lastBottom
         }
         reader.close();//關閉資源
         directory.close();//關閉鏈接
        
        }catch(Exception e){
            e.printStackTrace();
        }

至此,咱們已經瞭解了lucene中的分頁技術,至於,咱們在項目中該如何使用,都要根據咱們的實際狀況處理,由於分頁技術經常會跟其餘的,排序,過濾,評分等一些技術結合使用。

性能

相關文章
相關標籤/搜索