1. 程式人生 > >Solr中使用遊標進行深度分頁查詢以提高效率(適用的場景下)

Solr中使用遊標進行深度分頁查詢以提高效率(適用的場景下)

通常,我們的應用系統,如果要做一次全量資料的讀取,大多數時候,採用的方式會是使用分頁讀取的方式,然而
分頁讀取的方式,在大資料量的情況下,在solr裡面表現並不是特別好,因為它隨時可能會發生OOM的異常,在solr裡面
通過rows和start引數,非常方便分頁讀取,但是如果你的start=1000000 rows=10,那麼solr裡面會將前面100萬元資料的索引資訊讀取在記憶體裡面,這樣以來,非常耗記憶體,所以在solr裡面,分頁並不適合深度分頁。

深度分頁在solr裡面,更推薦使用遊標的方式,遊標是無狀態的,不會維護索引資料在記憶體裡面,僅僅記錄最後一個doc的計算值類似md5,然後每一次讀取,都會如此記錄最後一個值的mark,下一次通過這個mark便能快速的定位到第二頁上,如此往復,便能完成整個資料的讀取。而且耗費記憶體非常少。

假如現在有排好隊的10個人等待買飯,而一個房間裡面最多一次只能進2個人,那麼我們就可以將這個2個人,編號順序,1和2,他們打完飯後,讓2號的人通知,下一組2個人,進來打飯,如此往復
所有人都能吃到飯,這就類似solr中游標的使用。

使用遊標的方式讀取資料,也有一些約束或者缺點:

(1)查詢條件裡面必須有cursorMark引數,而且必須不能有start引數
(2)查詢的條件裡必須按照主鍵排序(升序或降序),如果沒有這個條件,主鍵重複,那麼會造成多個遊標的mark值,這樣以來下一次請求就不知道如何定位了,而且有可能出現重複讀資料的情況
(3)如果一個分頁的系統,按照指定頁碼跳轉的功能,這樣實現的功能是實現不了的,因為遊標一旦讀取了,就不能再返回上一次的位置了,這種業務最好使用start+rows搞定。

solrj實現程式碼例子:

//遊標查詢
    public static void cursorQuery()throws Exception{
            //http solr服務
            HttpSolrClient sc=new HttpSolrClient("http://localhost:8983/solr/one");
            //solr查詢封裝
            SolrQuery sq =new SolrQuery();
                sq.setRows(2);//設定遊標一次讀的數量
                sq.set
("q", "*:*");//按條件檢索 sq.setSort("id", ORDER.asc);//根據主鍵排序 String cursorMark = CursorMarkParams.CURSOR_MARK_START;//遊標初始化 boolean done = false; while (!done) { sq.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);//變化遊標條件 QueryResponse rsp = sc.query(sq);//執行多次查詢讀取 String nextCursorMark = rsp.getNextCursorMark();//獲取下次遊標 //做一些操作資料的事 for(SolrDocument sd:rsp.getResults()){ System.out.println(sd.get("id")); } //如果兩次遊標一樣,說明資料拉取完畢,可以結束迴圈了 if (cursorMark.equals(nextCursorMark)) { done = true; } cursorMark = nextCursorMark; } //關閉連線 sc.close(); }