Solr遊標查詢提高翻頁效率
阿新 • • 發佈:2018-09-10
ppm 所有 println 52.0 1.0 extc pos sca stat
使用cursorMark深分頁
1、Solr4.7+
2、start=0(一直等於0),rows=6(需要返回的記錄條目)
3、第一次請求cursorMark=*,下一次請求用上次請求返回的cursortMark值
長期以來,我們一直有一個深分頁問題。如果直接跳到很靠後的頁數,查詢速度會比較慢。這是因為Solr的需要為查詢從開始遍歷所有數據。直到Solr的4.7這個問題一直沒有一個很好的解決方案。與最近發布的Solr的版本中,Solr使用了所謂的遊標大幅度提高深翻頁的性能。
問題
深分頁的問題是很清楚。Solr必須為返回的搜索結果準備一個列表,並返回它的一部分。如果該部分來源於該列表的前面並不難。但如果我們想返回第10000頁(每頁20條記錄)的數據,Solr需要準備一個包含大小為200000(10000 * 20)的列表。這樣,它不僅需要時間,還需要內存。
令人高興的是,Solr 4.7的發布改變了這一狀況,引入了遊標的概念。遊標是一個動態結構,不需要存儲在服務器上。遊標包含了查詢的結果的偏移量,因此,Solr的不再需要每次從頭開始遍歷結果直到我們想要的記錄,遊標的功能可以大幅提升深翻頁的性能。
用法
遊標的使用非常簡單。在第一個查詢中,我們需要傳遞一個額外的參數- cursorMark = *,告訴Solr返回遊標。在返回中除了搜索結果,我們還可以得到nextCursorMark信息。看看下面這個例子。
查詢
我們從一個簡單的查詢開始:
|
這裏我們傳入一個cursorMark = *參數,告訴Solr的,我們要使用的光標。
搜索結果
上面的查詢將返回以下搜索結果:
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">33</int> <lst name="params"> <str name="sort">score desc,id asc</str> <str name="start">0</str> <str name="q">*:*</str> <str name="cursorMark">*</str> <str name="rows">1</str> </lst> </lst> <result name="response" numFound="32" start="0"> <doc> <str name="id">0579B002</str> <str name="name">Canon PIXMA MP500 All-In-One Photo Printer</str> <str name="manu">Canon Inc.</str> <str name="manu_id_s">canon</str> <arr name="cat"> <str>electronics</str> <str>multifunction printer</str> <str>printer</str> <str>scanner</str> <str>copier</str> </arr> <arr name="features"> <str>Multifunction ink-jet color photo printer</str> <str>Flatbed scanner, optical scan resolution of 1,200 x 2,400 dpi</str> <str>2.5" color LCD preview screen</str> <str>Duplex Copying</str> <str>Printing speed up to 29ppm black, 19ppm color</str> <str>Hi-Speed USB</str> <str>memory card: CompactFlash, Micro Drive, SmartMedia, Memory Stick, Memory Stick Pro, SD Card, and MultiMediaCard</str> </arr> <float name="weight">352.0</float> <float name="price">179.99</float> <str name="price_c">179.99,USD</str> <int name="popularity">6</int> <bool name="inStock">true</bool> <str name="store">45.19214,-93.89941</str> <long name="_version_">1461375031699308544</long></doc> </result> <str name="nextCursorMark">AoIIP4AAACgwNTc5QjAwMg==</str> </response> |
我們看到,除了平時返回的結果外,還多了一個遊標數據nextCursorMark,使用這個值作為我們翻下一頁的參數。
下一個查詢
提交下面這個查詢看一下:
|
結果如下:
<?xml version="1.0" encoding="UTF-8"?> <response> <lst name="responseHeader"> <int name="status">0</int> <int name="QTime">2</int> <lst name="params"> <str name="sort">score desc,id asc</str> <str name="indent">true</str> <str name="q">*:*</str> <str name="cursorMark">AoIIP4AAACgwNTc5QjAwMg==</str> <str name="rows">1</str> </lst> </lst> <result name="response" numFound="32" start="0"> <doc> <str name="id">100-435805</str> <str name="name">ATI Radeon X1900 XTX 512 MB PCIE Video Card</str> <str name="manu">ATI Technologies</str> <str name="manu_id_s">ati</str> <arr name="cat"> <str>electronics</str> <str>graphics card</str> </arr> <arr name="features"> <str>ATI RADEON X1900 GPU/VPU clocked at 650MHz</str> <str>512MB GDDR3 SDRAM clocked at 1.55GHz</str> <str>PCI Express x16</str> <str>dual DVI, HDTV, svideo, composite out</str> <str>OpenGL 2.0, DirectX 9.0</str> </arr> <float name="weight">48.0</float> <float name="price">649.99</float> <str name="price_c">649.99,USD</str> <int name="popularity">7</int> <bool name="inStock">false</bool> <date name="manufacturedate_dt">2006-02-13T00:00:00Z</date> <str name="store">40.7143,-74.006</str> <long name="_version_">1461375031846109184</long></doc> </result> <str name="nextCursorMark">AoIIP4AAACoxMDAtNDM1ODA1</str> </response> |
現在,返回的nextCursorMark變化了,這是新的遊標。
進一步查詢
接下來的查詢就很清楚了,使用cursorMark參數不斷翻頁,再來一次:
|
總結
Solr的4.7引入的這個遊標參數非常簡單,大大提升了翻頁的效果,詳細的測試報告看這裏:
http://searchhub.org/2013/12/12/coming-soon-to-solr-efficient-cursor-based-iteration-of-large-result-sets
java實現:
- static void deepPaging() throws SolrServerException{
- HttpSolrServer server = new HttpSolrServer("http://192.168.238.133:8080/solr/collection1");
- server.setSoTimeout(10000);
- server.setConnectionTimeout(10000);
- server.setDefaultMaxConnectionsPerHost(12);
- server.setAllowCompression(true);
- SolrQuery query = new SolrQuery();
- query.setQuery( "*:*" );
- query.setRows(4);
- query.addSort("price",ORDER.desc).addSort("id", ORDER.desc);
- query.set(CursorMarkParams.CURSOR_MARK_PARAM, "*");
- QueryResponse rsp = server.query( query );
- List<CursorMark> beans = rsp.getBeans(CursorMark.class);
- System.out.println(rsp.getNextCursorMark());//得到下一個遊標
- for (CursorMark cursorMark : beans) {
- System.out.println(cursorMark);
- }
- }
Solr遊標查詢提高翻頁效率